2017-06-26 102 views
0

我使用CCKeyDerivationPBKDF获取伪随机生成的派生密钥时遇到问题。使用CCKeyDerivationPBKDF获取派生密钥

这里是我使用的@zaph代码:

// password  password String 
// salt   salt Data 
// keyByteCount number of key bytes to generate 
// rounds  Iteration rounds 
//  
// returns  Derived key 


func pbkdf2SHA1(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? { 
    return pbkdf2(hash:CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds) 
} 

func pbkdf2SHA256(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? { 
    return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds) 
} 

func pbkdf2SHA512(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? { 
    return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA512), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds) 
} 

func pbkdf2(hash :CCPBKDFAlgorithm, password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? { 
    let passwordData = password.data(using:String.Encoding.utf8)! 
    var derivedKeyData = Data(repeating:0, count:keyByteCount) 

    let derivationStatus = derivedKeyData.withUnsafeMutableBytes {derivedKeyBytes in 
     salt.withUnsafeBytes { saltBytes in 

      CCKeyDerivationPBKDF(
       CCPBKDFAlgorithm(kCCPBKDF2), 
       password, passwordData.count, 
       saltBytes, salt.count, 
       hash, 
       UInt32(rounds), 
       derivedKeyBytes, derivedKeyData.count) 
     } 
    } 

    if (derivationStatus != 0) { 
     print("Error: \(derivationStatus)") 
     return nil; 
    } 



    return derivedKeyData 
} 

我的问题是,它使生成的每个调用相同的派生的密钥。 我试图解密是与Rfc2898DeriveBytes .Net的侧加密的数据:

var saltBytes = Encoding.ASCII.GetBytes(salt); 
var key = new Rfc2898DeriveBytes(Inputkey, saltBytes); 

var aesAlg = new RijndaelManaged(); 
aesAlg.Key = key.GetBytes(aesAlg.KeySize/8); // default keySize 256 
aesAlg.IV = key.GetBytes(aesAlg.BlockSize/8); // default blockSize 128 

在.NET方面,Rfc2898DeriveBytes返回新的随机字节集,但我的银行代码只产生每个调用相同的顺序。 Swift那边的序列生成有什么问题?

编辑1:当我使用从.net生成的Rfc2898DeriveBytes的密钥和IV字节序列试图解密在.net中加密的数据时,它工作正常。

编辑2:好的,我发现Rfc2898DeriveBytes第一次使用GetBytes方法的结果与Swift PBKDF2结果相同。第二个调用GetBytes给出了完全不同的结果。这是为什么?如果我为此解决方案,那么我的解密应该工作。

aesAlg.Key = key.GetBytes(aesAlg.KeySize/8); // (1) - the same result as in Swift implementation 
aesAlg.IV = key.GetBytes(aesAlg.BlockSize/8); // (2) - completly different result 

我是否错误地初始化了Swift中的IV?

+1

您需要在生产中每次使用不同的盐。在加密和解密中需要使用相同的IV,一种常见的方法是使用IV来加密数据的前缀,而不需要保密。在aesAlg.IV的情况下,函数初始化了一次,并且对它进行了两次调用。多次使用同一个密钥的同一个IV是一个安全问题。 – zaph

+0

@ zaph非常感谢您的回复。对不起,我还是不明白。对于AES256,IV总是长16字节?你的意思是,GetBytes方法不应该在同一个实例上调用两次?我可能会问很愚蠢的问题,因为我在这个主题上是新的。 – PiotrCh

+1

AES IV总是16字节。每次使用相同的加密密钥时,它需要不同。它最好作为加密数据的一部分通过解密,通常用于加密数据。只要是随机的,IV并不重要。如果使用一种方法为同一个不安全的密钥生成相同的IV。 – zaph

回答

0

.NET实现实际上是一个流。要从Apple版本获得相同的答案,您应该在一次调用中要求提供您需要的总字节数,然后将其分成您需要的任何部分。

+0

谢谢你的回应我会检查。 – PiotrCh