使用HMAC SHA1的CCKeyDerivationPBKDF经常返回-1

当我从#import 使用CCKeyDerivationPBKDF ,它返回-1 ,这是一个未定义的结果。 我不知道我是否想念一些东西。 如果我使用HMAC MD5或其他算法,它可以返回Success,只有当我使用HMAC SHA1它才会返回错误状态。

 int feedback = CCKeyDerivationPBKDF(kCCPBKDF2, clearTextData.bytes, clearTextData.length, secretData.bytes, secretData.length, kCCHmacAlgSHA1, 2048, result, sizeof(result)); 

我注意到你正在使用kCCHmacAlgSHA1而不是kCCPRFHmacAlgSHA1 ,这可能是错误。

这对我有用:

 NSData *keyData = [@"password" dataUsingEncoding:NSUTF8StringEncoding]; NSData *salt = [@"salt" dataUsingEncoding:NSUTF8StringEncoding]; uint rounds = 2048; uint keySize = kCCKeySizeAES128; NSMutableData *derivedKey = [NSMutableData dataWithLength:keySize]; CCKeyDerivationPBKDF(kCCPBKDF2, // algorithm keyData.bytes, // password keyData.length, // passwordLength salt.bytes, // salt salt.length, // saltLen kCCPRFHmacAlgSHA1, // PRF rounds, // rounds derivedKey.mutableBytes, // derivedKey derivedKey.length); // derivedKeyLen NSLog(@"derivedKey: %@", derivedKey); 

输出:
derivedKey: <2c13cb7a d3468748 5c3f3d4f 18ebddbd>

斯威夫特3

 let password = "TestPassword" let salt = Data("salt" .utf8); let keySize = kCCKeySizeAES128; let rounds = 2048 var derivedKeyData = Data(repeating:0, count:keySize) let derivationStatus = derivedKeyData.withUnsafeMutableBytes {derivedKeyBytes in salt.withUnsafeBytes { saltBytes in CCKeyDerivationPBKDF( CCPBKDFAlgorithm(kCCPBKDF2), password, password.utf8.count, saltBytes, salt.count, UInt32(kCCPRFHmacAlgSHA1), UInt32(rounds), derivedKeyBytes, derivedKeyData.count) } } print("derivedKeyData: \(derivedKeyData.map { String(format: "%02hhx", $0) }.joined())") 

输出:
derivedKeyData: 75d1f85fd64d170b3ffe66c7f1d1519a

来自日落文档部分的更通用的解决方案:

基于密码的密钥派生2(Swift 3+)

基于密码的密钥派生既可用于从密码文本中导出加密密钥,也可用于保存密码以进行身份​​validation。

可以使用几种哈希算法,包括SHA1,SHA256,SHA512,这些算法由此示例代码提供。

rounds参数用于使计算变慢,以便攻击者必须在每次尝试上花费大量时间。 典型的延迟值在100ms到500ms之间,如果有不可接受的性能,可以使用更短的值。

此示例需要Common Crypto
有必要为项目建立一个桥接头:
#import
Security.framework添加到项目中。

参数:

 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:CCPBKDFAlgorithm(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 } 

用法示例:

 let password = "password" //let salt = "saltData".data(using: String.Encoding.utf8)! let salt = Data(bytes: [0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61]) let keyByteCount = 16 let rounds = 100000 let derivedKey = pbkdf2SHA1(password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds) print("derivedKey (SHA1): \(derivedKey! as NSData)") 

示例输出:

 derivedKey (SHA1): <6b9d4fa3 0385d128 f6d196ee 3f1d6dbf> 

基于密码的密钥派生校准(Swift 3+)

确定当前平台上特定延迟使用的PRF轮次数。

有几个参数默认为不应对圆计数产生实质影响的代表值。

 password Sample password. salt Sample salt. msec Targeted duration we want to achieve for a key derivation. returns The number of iterations to use for the desired processing time. func pbkdf2SHA1Calibrate(password: String, salt: Data, msec: Int) -> UInt32 { let actualRoundCount: UInt32 = CCCalibratePBKDF( CCPBKDFAlgorithm(kCCPBKDF2), password.utf8.count, salt.count, CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1), kCCKeySizeAES256, UInt32(msec)); return actualRoundCount } 

用法示例:

 let saltData = Data(bytes: [0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61]) let passwordString = "password" let delayMsec = 100 let rounds = pbkdf2SHA1Calibrate(password:passwordString, salt:saltData, msec:delayMsec) print("For \(delayMsec) msec delay, rounds: \(rounds)") 

示例输出:

 For 100 msec delay, rounds: 93457