首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Swift 2&3中使用CommonCrypto实现PBKDF2

如何在Swift 2&3中使用CommonCrypto实现PBKDF2
EN

Stack Overflow用户
提问于 2016-10-31 05:02:27
回答 3查看 5.9K关注 0票数 10

我试图使用CommonCrypto在Swift 2中使用PBKDF2对密码进行散列,因为它的高性能以及它是开源的。

我已经设法让CommonCrypto在Swift中使用模块映射,但是有人能告诉我使用CommonCrypto在Swift 2中使用PBKDF2的代码吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-10-31 12:35:13

代码语言:javascript
复制
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是哈希类型,如kCCPRFHmacAlgSHA1kCCPRFHmacAlgSHA256kCCPRFHmacAlgSHA512

示例来自日落文档部分:

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

基于密码的密钥派生既可用于从密码文本派生加密密钥,也可用于为身份验证目的保存密码。

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

each参数用于使计算速度慢,以便攻击者在每次尝试时都要花费大量时间。典型的延迟值在100到500 is之间,如果有不可接受的性能,可以使用较短的值。

此示例需要通用密码

有必要为项目设置一个桥接头:

#import <CommonCrypto/CommonCrypto.h>

Security.framework添加到项目中。

参数:

代码语言:javascript
复制
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
}

示例用法:

代码语言:javascript
复制
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)")

示例输出:

代码语言:javascript
复制
derivedKey (SHA1): <6b9d4fa3 0385d128 f6d196ee 3f1d6dbf>

基于密码的密钥推导校准

此示例需要通用密码(它需要为项目设置一个桥接头):

代码语言:javascript
复制
#import <CommonCrypto/CommonCrypto.h>

将Security.framework添加到项目中。

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

一些参数默认为表示值,这些值不应对整次计数产生重大影响。

代码语言:javascript
复制
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)

代码语言:javascript
复制
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
}

示例用法:

代码语言:javascript
复制
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)")

示例输出:

代码语言:javascript
复制
For 100 msec delay, rounds: 93457

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

代码语言:javascript
复制
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
}

示例用法:

代码语言:javascript
复制
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)")
票数 10
EN

Stack Overflow用户

发布于 2019-01-23 15:58:50

对于Swift 4,工作代码应该是

代码语言:javascript
复制
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
}
票数 4
EN

Stack Overflow用户

发布于 2020-07-01 16:58:15

下面是一个有用的Swift 5示例,消除了所有编译器警告:

代码语言:javascript
复制
private func pbkdf2(password: String, saltData: Data, keyByteCount: Int, prf: CCPseudoRandomAlgorithm, 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,
                prf,
                UInt32(rounds),
                keyBuffer,
                derivedCount)
        }
    }
    return derivationStatus == kCCSuccess ? derivedKeyData : nil
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40336819

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档