使用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