使用 swift 2.0 生成钥匙串密钥

Posted

技术标签:

【中文标题】使用 swift 2.0 生成钥匙串密钥【英文标题】:Generate keychain key with swift 2.0 【发布时间】:2015-10-05 14:28:04 【问题描述】:

创建密钥对(私有、公共)的函数

public func generateKeyPair(publicKeyTag: String, privateKeyTag:String, keySize: Int) -> KeyPair? 

    let privateKeyAttr: [String: AnyObject] = [
        kSecAttrIsPermanent as String: kCFBooleanTrue,
        kSecAttrApplicationTag as String: privateKeyTag
    ];

    let publicKeyAttr: [String: AnyObject] = [
        kSecAttrIsPermanent as String: kCFBooleanTrue,
        kSecAttrApplicationTag as String: publicKeyTag
    ];

    let keyPairAttr: [String: AnyObject] = [
        kSecAttrKeyType as! String: kSecAttrKeyTypeRSA,
        kSecAttrKeySizeInBits as! String: keySize,
        kSecPrivateKeyAttrs as! String: privateKeyAttr,
        kSecPublicKeyAttrs as! String: publicKeyAttr
    ];

    var publicKeyPtr, privateKeyPtr: Unmanaged<SecKey>?;

    let error = SecKeyGeneratePair(keyPairAttr, &publicKeyPtr, &privateKeyPtr)

    if( result != errSecSuccess )
        return nil
    

    let publicKey = publicKeyPtr!.takeRetainedValue()
    let privateKey = privateKeyPtr!.takeRetainedValue()
    return KeyPair(publicKey: publicKey, privateKey: privateKey)

加注

Cannot convert value of type 'inout Unmanged<SecKey>?' ... expected argument type 'UnsafeMutablePointer<SecKey?> ...'

当我查找 the api for SecKeyGeneratePair 时,这听起来是 sound,所以让我们更改 publicKeyPtr, privateKeyPtr 的类型:

public func generateKeyPair(publicKeyTag: String, privateKeyTag:String, keySize: Int) -> KeyPair ? 

    let privateKeyAttr: [String: AnyObject] = [
        kSecAttrIsPermanent as String: kCFBooleanTrue,
        kSecAttrApplicationTag as String: privateKeyTag
    ]

    let publicKeyAttr: [String: AnyObject] = [
        kSecAttrIsPermanent as String: kCFBooleanTrue,
        kSecAttrApplicationTag as String: publicKeyTag
    ]

    let parameters: [String: AnyObject] = [
        kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
        kSecAttrKeySizeInBits as String: keySize,
        kSecPrivateKeyAttrs as String: privateKeyAttr,
        kSecPublicKeyAttrs as String: publicKeyAttr
    ]

    var publicKeyPtr: UnsafeMutablePointer<SecKey?> = nil
    var privateKeyPtr: UnsafeMutablePointer<SecKey?> = nil

    let result = SecKeyGeneratePair(parameters, publicKeyPtr, privateKeyPtr)

    if( result != errSecSuccess )
        return nil
    

    let publicKey = Unmanaged<SecKey>.fromOpaque(COpaquePointer(publicKeyPtr)).takeRetainedValue()
    let privateKey = Unmanaged<SecKey>.fromOpaque(COpaquePointer(privateKeyPtr)).takeRetainedValue()

    publicKeyPtr.destroy()
    privateKeyPtr.destroy()

    return KeyPair(publicKey: publicKey, privateKey: privateKey)

但是当我使用该函数时,publicKey 和 privateKey 会引发:

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_i386_INVOP, ...

当我插入断点时,我意识到指针(`publicKeyPtr,privateKeyPtr)从未设置。

那么如何将 swift 1.2 代码迁移到 swift 2.0 呢?

【问题讨论】:

【参考方案1】:

试试:

public func generateKeyPair(publicKeyTag: String, privateKeyTag:String, keySize: Int) -> KeyPair?  

    let privateKeyAttr: [NSString: AnyObject] = [
        kSecAttrIsPermanent: true,
        kSecAttrApplicationTag: privateKeyTag
    ]
    let publicKeyAttr: [NSString: AnyObject] = [
        kSecAttrIsPermanent: true,
        kSecAttrApplicationTag: publicKeyTag
    ]
    let parameters: [NSString: AnyObject] = [
        kSecAttrKeyType: kSecAttrKeyTypeRSA,
        kSecAttrKeySizeInBits: keySize,
        kSecPrivateKeyAttrs: privateKeyAttr,
        kSecPublicKeyAttrs: publicKeyAttr
    ]

    var publicKey: SecKey?
    var privateKey: SecKey?
    let result = SecKeyGeneratePair(parameters, &publicKey, &privateKey)

    if result != errSecSuccess 
        return nil
    
    return KeyPair(publicKey: publicKey!, privateKey: privateKey!)

您可以将&amp; 表达式传入-传出UnsafeMutablePointer 参数。

另请参阅:swift 2.0 keychain type errors for SecItemCopyMatching

【讨论】:

不应该kSecAttrApplicationTagNSData 吗?此代码编译但崩溃。

以上是关于使用 swift 2.0 生成钥匙串密钥的主要内容,如果未能解决你的问题,请参考以下文章

代码符号想要使用钥匙串中的密钥进行签名

使用 Swift 查询 iOS 钥匙串

从钥匙串“我的证书”中导出 p12 文件

以编程方式在 OS X 钥匙串中存储对称密钥

NE***Manager 中使用的 Swift 中的钥匙串引用

在钥匙串中存储用于加密密码的密钥的最佳位置在哪里