当前位置: 首页 > 面试题库 >

Swift:如何从Swift调用CCKeyDerivationPBKDF

莘睿
2023-03-14
问题内容

我正在尝试从Swift调用CCKeyDerivationPBKDF。

我已经在Project-Bridging-Header.h中导入了所需的标头:

#import <CommonCrypto/CommonKeyDerivation.h>

(顺便说一句,在我的项目中导入其他Objective C代码时,桥接头似乎正常工作)。

在Xcode中,我可以从.swift文件跳转到此处显示的定义:

int 
CCKeyDerivationPBKDF( CCPBKDFAlgorithm algorithm, const char *password, size_t passwordLen,
                      const uint8_t *salt, size_t saltLen,
                      CCPseudoRandomAlgorithm prf, uint rounds, 
                      uint8_t *derivedKey, size_t derivedKeyLen)

最后,当我尝试像这样调用函数时:

let result = CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2), NSString(password).UTF8String, size_t(passwordLength), UnsafePointer<UInt8>(salt.bytes), size_t(salt.length), CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256), uint(actualRoundCount), UnsafeMutablePointer<UInt8>(derivedKey.mutableBytes), size_t(derivedKey.length));

…我得到这个编译器错误:

无法使用类型为’(CCPBKDFAlgorithm,UnsafePointer,size_t,UnsafePointer,size_t,CCPseudoRandomAlgorithm,uint,UnsafeMutablePointer,size_t)的参数列表调用’init’

我相信所有强制转换都是正确的(实际上,编译器错误帮助我识别了每个参数的每个问题)-这使我认为编译器理解了我调用CCKeyDerivationPBKDF的意图。

但是,在所有其他强制转换错误消失之后,编译器感到困惑,并认为我正在尝试使用初始化程序构造一个类。

希望有人可以告诉我我的方式的错误。

(Xcode 6 beta 7)

根据要求,在上下文中提供完整代码:

class func generateAesKeyForPassword(password: String, salt: NSData, roundCount: UInt?, error: NSErrorPointer) -> (key: NSData, actualRoundCount: UInt)?
    {
        let derivedKey = NSMutableData(length: kCCKeySizeAES256)

        let passwordLength = size_t(password.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))

        var actualRoundCount: UInt

        if roundCount != nil
        {
            actualRoundCount = roundCount!
        }
        else
        {
            actualRoundCount = UInt(CCCalibratePBKDF(CCPBKDFAlgorithm(kCCPBKDF2), passwordLength, UInt(salt.length), CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256), UInt(derivedKey.length), UInt32(300) /* milliseconds */));
        }

        let result = CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2), NSString(password).UTF8String, size_t(passwordLength), UnsafePointer<UInt8>(salt.bytes), size_t(salt.length), CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256), uint(actualRoundCount), UnsafeMutablePointer<UInt8>(derivedKey.mutableBytes), size_t(derivedKey.length));
        if result != 0
        {
            let errorDescription = "CCKeyDerivationPBKDF failed with error: '\(result)'"

            error.memory = MyError(domain: ClientErrorType.errorDomain, code: Int(result), descriptionText: errorDescription)

            return nil
        }

        return (NSData(data: derivedKey), actualRoundCount)
    }

问题答案:

斯威夫特3:

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

此示例代码提供了多种可用的哈希算法,包括SHA1,SHA256,SHA512。

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

此示例需要通用加密
。必须在项目中具有桥接头:
#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>

Swift 2.x:

参数类型和类对实例方法的微小更改,以进行测试。

func generateAesKeyForPassword(password: String, salt: NSData, roundCount: Int?, error: NSErrorPointer) -> (key: NSData, actualRoundCount: UInt32)?
{
    let nsDerivedKey = NSMutableData(length: kCCKeySizeAES256)
    var actualRoundCount: UInt32

    // Create Swift intermediates for clarity in function calls
    let algorithm: CCPBKDFAlgorithm        = CCPBKDFAlgorithm(kCCPBKDF2)
    let prf:       CCPseudoRandomAlgorithm = CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256)
    let saltBytes  = UnsafePointer<UInt8>(salt.bytes)
    let saltLength = size_t(salt.length)
    let nsPassword        = password as NSString
    let nsPasswordPointer = UnsafePointer<Int8>(nsPassword.cStringUsingEncoding(NSUTF8StringEncoding))
    let nsPasswordLength  = size_t(nsPassword.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
    var nsDerivedKeyPointer = UnsafeMutablePointer<UInt8>(nsDerivedKey.mutableBytes)
    let nsDerivedKeyLength = size_t(nsDerivedKey.length)
    let msec: UInt32 = 300

    if roundCount != nil {
        actualRoundCount = UInt32(roundCount!)
    }
    else {
        actualRoundCount = CCCalibratePBKDF(
            algorithm,
            nsPasswordLength,
            saltLength,
            prf,
            nsDerivedKeyLength,
            msec);
    }

    let result = CCKeyDerivationPBKDF(
        algorithm,
        nsPasswordPointer,   nsPasswordLength,
        saltBytes,           saltLength,
        prf,                 actualRoundCount,
        nsDerivedKeyPointer, nsDerivedKeyLength)

    if result != 0 {
        let errorDescription = "CCKeyDerivationPBKDF failed with error: '\(result)'"
        // error.memory = MyError(domain: ClientErrorType.errorDomain, code: Int(result), descriptionText: errorDescription)
        return nil
    }

    return (nsDerivedKey, actualRoundCount)
}

//增加了奖励:

func salt(#length:UInt) -> NSData {
    let salt        = NSMutableData(length: Int(length))
    var saltPointer = UnsafeMutablePointer<UInt8>(salt.mutableBytes)
    SecRandomCopyBytes(kSecRandomDefault, length, saltPointer);
    return salt
}

//测试电话:

let password   = "test pass"
let salt       = self.salt(length:32)
let roundCount = 300
var error: NSError?

let result = self.generateAesKeyForPassword(password, salt:salt, roundCount:roundCount, error:&error)
println("result: \(result)")

输出:

result: Optional((<d279ab8d 8ace67b7 abec844c b9979d20 f2bb0a7f 5af70502 085bf1e4 1016b20c>, 300))


 类似资料:
  • 问题内容: 有没有办法从Swift调用C例程? 许多iOS / Apple库仅是C语言,我仍然希望能够调用它们。 例如,我希望能够从Swift调用objc运行时库。 特别是,如何桥接iOS C标头? 问题答案: 是的,您当然可以与Apples C库进行交互。这里说明了如何。 基本上,C型,C指针等被翻译成对象斯威夫特,例如C 在夫特是一个。 我为另一个问题构建了一个小例子,该例子可以作为对C和Sw

  • 问题内容: 我正在尝试使我的javascript与快速代码交互,但不幸的是我没有成功。 目前,我只是尝试更改标题的颜色并显示一条消息,如下面的代码所示。 这是我的( index.html )代码: 这是我的( main.js -JavaScript )代码: 这是我的( ViewController.swift )代码: 问题答案: 您已正确设置了所有内容,但没有将实例分配给。由于配置包含Java

  • JSON似乎打印到浏览器窗口,所以我不完全确定这种方法有什么问题?请谁能提供一些帮助,为什么这可能不起作用? 谢谢

  • 问题内容: 我编写了如下代码块: 初始化后就可以了。将人员设置为时,不调用该方法。 问题答案: 问题在于操场不是现实生活。这只是不使用它们的又一个原因(我认为,对于苹果公司而言,这是一个可怕的错误)。使用真实的iOS应用项目,将按预期方式调用。 来自真实项目的示例: 这就是您期望的。

  • 问题内容: 我无法从Objective-C访问Swift Singleton。 swiftSharedInstance无法访问。 问题答案: 现在,我有以下解决方案。也许我忽略了一些使我能够直接访问“ swiftSharedInstance”的东西? 然后在ObjC中,我可以获取sharedInstance类方法(在导入xcode生成的swift标头绑定之后)

  • 问题内容: 有没有办法调用从Swift的dylib加载的C函数? 这是我的 dylib 文件: cppdemofile.cpp cppdemofile.h 编译为dylib并检查: …复制到… Swift程序 : 如何调用该函数?可以使用dylib吗?我应该改为将这些资源添加到我的迅速项目中吗? 问题答案: 从Swift 调用该函数是可能的,因为您已将其定义为与C关联。 使库成为Swift模块(如