我使用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?
您需要在生产中每次使用不同的盐。在加密和解密中需要使用相同的IV,一种常见的方法是使用IV来加密数据的前缀,而不需要保密。在aesAlg.IV的情况下,函数初始化了一次,并且对它进行了两次调用。多次使用同一个密钥的同一个IV是一个安全问题。 – zaph
@ zaph非常感谢您的回复。对不起,我还是不明白。对于AES256,IV总是长16字节?你的意思是,GetBytes方法不应该在同一个实例上调用两次?我可能会问很愚蠢的问题,因为我在这个主题上是新的。 – PiotrCh
AES IV总是16字节。每次使用相同的加密密钥时,它需要不同。它最好作为加密数据的一部分通过解密,通常用于加密数据。只要是随机的,IV并不重要。如果使用一种方法为同一个不安全的密钥生成相同的IV。 – zaph