基於密碼的金鑰派生 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>