我正在尝试使用CommonCrypto在Swift 2中使用PBKDF2来散列密码,因为它具有高性能并且还因为它是开源的
我已经设法让使用模块映射在Swift中使用CommonCrypto,但有人可以告诉我使用CommonCrypto在Swift 2中使用PBKDF2进行散列的代码
答案 0 :(得分:6)
func pbkdf2(hash :CCPBKDFAlgorithm, password: String, salt: [UInt8], keyCount: Int, rounds: UInt32!) -> [UInt8]! {
let derivedKey = [UInt8](count:keyCount, repeatedValue:0)
let passwordData = password.dataUsingEncoding(NSUTF8StringEncoding)!
let derivationStatus = CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
UnsafePointer<Int8>(passwordData.bytes), passwordData.length,
UnsafePointer<UInt8>(salt), salt.count,
CCPseudoRandomAlgorithm(hash),
rounds,
UnsafeMutablePointer<UInt8>(derivedKey),
derivedKey.count)
if (derivationStatus != 0) {
print("Error: \(derivationStatus)")
return nil;
}
return derivedKey
}
hash
是哈希类型,例如kCCPRFHmacAlgSHA1
,kCCPRFHmacAlgSHA256
,kCCPRFHmacAlgSHA512
。
基于密码的密钥派生2(Swift 3 +)
基于密码的密钥派生既可用于从密码文本中导出加密密钥,也可用于保存密码以进行身份验证。
可以使用几种哈希算法,包括SHA1,SHA256,SHA512,这些算法由此示例代码提供。
rounds参数用于使计算变慢,以便攻击者必须在每次尝试上花费大量时间。典型的延迟值在100ms到500ms之间,如果有不可接受的性能,可以使用更短的值。
此示例需要Common Crypto
项目必须有一个桥接标题:
#import <CommonCrypto/CommonCrypto.h>
将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>
基于密码的密钥派生校准
此示例需要Common Crypto 有必要为项目建立一个桥接头:
#import <CommonCrypto/CommonCrypto.h>
将Security.framework添加到项目中。
确定当前平台上特定延迟使用的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.
基于密码的密钥派生校准(Swift 3)
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
基于密码的密钥派生校准(Swift 2.3)
func pbkdf2SHA1Calibrate(password:String, salt:[UInt8], msec:Int) -> UInt32 {
let actualRoundCount: UInt32 = CCCalibratePBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password.utf8.count,
salt.count,
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1),
kCCKeySizeAES256,
UInt32(msec));
return actualRoundCount
}
使用示例:
let saltData = [UInt8]([0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61])
let passwordString = "password"
let delayMsec = 100
let rounds = pbkdf2SHA1Calibrate(passwordString, salt:saltData, msec:delayMsec)
print("For \(delayMsec) msec delay, rounds: \(rounds)")
答案 1 :(得分:2)
对于Swift 4,工作代码应该是
func pbkdf2(hash: CCPBKDFAlgorithm, password: String, salt: String, keyByteCount: Int, rounds: Int) -> Data? {
guard let passwordData = password.data(using: .utf8), let saltData = salt.data(using: .utf8) else { return nil }
var derivedKeyData = Data(repeating: 0, count: keyByteCount)
let derivedCount = derivedKeyData.count
let derivationStatus = derivedKeyData.withUnsafeMutableBytes { derivedKeyBytes in
saltData.withUnsafeBytes { saltBytes in
CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password,
passwordData.count,
saltBytes,
saltData.count,
hash,
UInt32(rounds),
derivedKeyBytes,
derivedCount)
}
}
return derivationStatus == kCCSuccess ? derivedKeyData : nil
}
答案 2 :(得分:1)
这是一个有效的Swift 5示例,摆脱了所有编译器警告:
private func pbkdf2(hash: CCPBKDFAlgorithm, password: String, saltData: Data, keyByteCount: Int, rounds: Int) -> Data? {
guard let passwordData = password.data(using: .utf8) else { return nil }
var derivedKeyData = Data(repeating: 0, count: keyByteCount)
let derivedCount = derivedKeyData.count
let derivationStatus: Int32 = derivedKeyData.withUnsafeMutableBytes { derivedKeyBytes in
let keyBuffer: UnsafeMutablePointer<UInt8> =
derivedKeyBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
return saltData.withUnsafeBytes { saltBytes -> Int32 in
let saltBuffer: UnsafePointer<UInt8> = saltBytes.baseAddress!.assumingMemoryBound(to: UInt8.self)
return CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password,
passwordData.count,
saltBuffer,
saltData.count,
hash,
UInt32(rounds),
keyBuffer,
derivedCount)
}
}
return derivationStatus == kCCSuccess ? derivedKeyData : nil
}