如何在 Swift 2 & 中为 PBKDF2 使用 CommonCrypto3 [英] How to use CommonCrypto for PBKDF2 in Swift 2 & 3

查看:38
本文介绍了如何在 Swift 2 & 中为 PBKDF2 使用 CommonCrypto3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 CommonCrypto 在 Swift 2 中使用 PBKDF2 散列密码,因为它的高性能以及它是开源的

我已经设法使用模块映射使 CommonCrypto 在 Swift 中工作,但有人可以告诉我使用 CommonCrypto 在 Swift 2 中使用 PBKDF2 进行散列的代码

解决方案

func pbkdf2(hash :CCPBKDFAlgorithm, password: String, salt: [UInt8], keyCount: Int, rounds: UInt32!) ->[UInt8]!{让derivedKey = [UInt8](count:keyCount,repeatValue:0)让 passwordData = password.dataUsingEncoding(NSUTF8StringEncoding)!让 derivationStatus = CCKeyDerivationPBKDF(CCPBKDF算法(kCCPBKDF2),UnsafePointer(passwordData.bytes)、passwordData.length、UnsafePointer(salt), salt.count,CCPseudoRandomAlgorithm(hash),回合,UnsafeMutablePointer(derivedKey),派生密钥.计数)如果(派生状态!= 0){打印(错误:\(derivationStatus)")返回零;}返回派生密钥}

hash 是散列类型,例如 kCCPRFHmacAlgSHA1kCCPRFHmacAlgSHA256kCCPRFHmacAlgSHA512.

废止文档部分的示例:

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

基于密码的密钥派生既可用于从密码文本派生加密密钥,也可用于保存密码以进行身份​​验证.

可以使用多种哈希算法,包括此示例代码提供的 SHA1、SHA256、SHA512.

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

这个例子需要通用加密
必须要有一个到项目的桥接头:
#import
Security.framework 添加到项目中.

参数:

password 密码字符串盐盐数据keyByteCount 要生成的密钥字节数轮次 迭代轮次返回派生键func pbkdf2SHA1(password: String, salt: Data, keyByteCount: Int, rounds: Int) ->数据?{return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA1), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)}func pbkdf2SHA256(password: String, salt: Data, keyByteCount: Int, rounds: Int) ->数据?{return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)}func pbkdf2SHA512(password: String, salt: Data, keyByteCount: Int, rounds: Int) ->数据?{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) ->数据?{让 passwordData = password.data(使用:String.Encoding.utf8)!varderivedKeyData = Data(repeating:0, count:keyByteCount)让 derivationStatus =derivedKeyData.withUnsafeMutableBytes {derivedKeyBytes insalt.withUnsafeBytes { saltBytes inCCKeyDerivationPBKDF(CCPBKDF算法(kCCPBKDF2),密码,passwordData.count,saltBytes,salt.count,哈希,UInt32(回合),派生密钥字节、派生密钥数据.计数)}}如果(派生状态!= 0){打印(错误:\(derivationStatus)")返回零;}返回派生密钥数据}

示例用法:

let password = "password";//let salt = "saltData".data(使用:String.Encoding.utf8)!让盐 = 数据(字节:[0x73、0x61、0x6c、0x74、0x44、0x61、0x74、0x61])让 keyByteCount = 16让轮数 = 100000让衍生密钥 = pbkdf2SHA1(密码:密码,salt:salt,keyByteCount:keyByteCount,rounds:rounds)打印(派生密钥(SHA1):\(派生密钥!作为NSData)")

示例输出:

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

基于密码的密钥派生校准

此示例需要 Common Crypto必须有一个到项目的桥接头:

#import 

将 Security.framework 添加到项目中.


确定用于当前平台上特定延迟的 PRF 轮数.

几个参数默认为代表值,不会对轮数产生实质性影响.

password 示例密码.盐 样品盐.毫秒 我们希望为密钥派生实现的目标持续时间.返回用于所需处理时间的迭代次数.

<块引用>

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

func pbkdf2SHA1Calibrate(password: String, salt: Data, msec: Int) ->UInt32 {让 actualRoundCount: UInt32 = CCCalibratePBKDF(CCPBKDF算法(kCCPBKDF2),密码.utf8.count,salt.count,CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1),kCCKeySizeAES256,UInt32(毫秒));返回实际轮数}

示例用法:

let saltData = Data(bytes: [0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61])让 passwordString = 密码"让延迟毫秒 = 100让轮数 = pbkdf2SHA1Calibrate(密码:passwordString,salt:saltData,msec:delayMsec)打印(对于 \(delayMsec)毫秒延迟,轮次:\(轮次)")

示例输出:

对于 100 毫秒延迟,轮次:93457

<块引用>

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

func pbkdf2SHA1Calibrate(password:String, salt:[UInt8], msec:Int) ->UInt32 {让 actualRoundCount: UInt32 = CCCalibratePBKDF(CCPBKDF算法(kCCPBKDF2),密码.utf8.count,salt.count,CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA1),kCCKeySizeAES256,UInt32(毫秒));返回实际轮数}

示例用法:

let saltData = [UInt8]([0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61])让 passwordString = 密码"让延迟毫秒 = 100让轮 = pbkdf2SHA1Calibrate(passwordString, salt:saltData, msec:delayMsec)打印(对于 \(delayMsec)毫秒延迟,轮次:\(轮次)")

I am trying to use CommonCrypto to hash passwords using PBKDF2 in Swift 2 because of its high performance and also due to it being open source

I've already managed to get CommonCrypto working in Swift using module maps but can someone tell me the code for hashing with PBKDF2 in Swift 2 using CommonCrypto

解决方案

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 is the hash type such as kCCPRFHmacAlgSHA1, kCCPRFHmacAlgSHA256, kCCPRFHmacAlgSHA512.

Example from sunsetted documentation section:

Password Based Key Derivation 2 (Swift 3+)

Password Based Key Derivation can be used both for deriving an encryption key from password text and saving a password for authentication purposes.

There are several hash algorithms that can be used including SHA1, SHA256, SHA512 which are provided by this example code.

The rounds parameter is used to make the calculation slow so that an attacker will have to spend substantial time on each attempt. Typical delay values fall in the 100ms to 500ms, shorter values can be used if there is unacceptable performance.

This example requires Common Crypto
It is necessary to have a bridging header to the project:
#import <CommonCrypto/CommonCrypto.h>
Add the Security.framework to the project.

Parameters:

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
}

Example usage:

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)")

Example Output:

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

Password Based Key Derivation Calibration

This example requires Common Crypto It is necessary to have a bridging header to the project:

#import <CommonCrypto/CommonCrypto.h>

Add the Security.framework to the project.


Determine the number of PRF rounds to use for a specific delay on the current platform.

Several parameters are defaulted to representative values that should not materially affect the round count.

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.

Password Based Key Derivation Calibration (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
}

Example usage:

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)")

Example Output:

For 100 msec delay, rounds: 93457

Password Based Key Derivation Calibration (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
}

Example usage:

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)")

这篇关于如何在 Swift 2 &amp; 中为 PBKDF2 使用 CommonCrypto3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆