【问题标题】:How do I export a public key <SecKey> that was generated using SecKeyGeneratePair to be used on a server?如何导出使用 SecKeyGeneratePair 生成的公钥 <SecKey> 以在服务器上使用?
【发布时间】:2015-03-07 07:58:10
【问题描述】:

我使用 SecKeyGeneratePair 生成了一个 keeper。

        var publicKeyPtr, privateKeyPtr: Unmanaged<SecKey>?

        let publicKeyParameters: [String: AnyObject] = [
            kSecAttrIsPermanent: true,
            kSecAttrApplicationTag: "com.example.site.public"
        ]
        let privateKeyParameters: [String: AnyObject] = [
            kSecAttrIsPermanent: true,
            kSecAttrApplicationTag: "com.example.site.private"
        ]
        let parameters: [String: AnyObject] = [
            kSecAttrKeyType: kSecAttrKeyTypeRSA,
            kSecAttrKeySizeInBits: 2048,
            kSecPublicKeyAttrs.takeUnretainedValue() as String: publicKeyParameters,
            kSecPrivateKeyAttrs.takeUnretainedValue() as String: privateKeyParameters
        ]
        let result = SecKeyGeneratePair(parameters, &publicKeyPtr, &privateKeyPtr)
        let publicKey = publicKeyPtr!.takeRetainedValue()
        let privateKey = privateKeyPtr!.takeRetainedValue()
        let blockSize = SecKeyGetBlockSize(publicKey)

如果我打印出 publicKey,我可以看到模数,我很确定这是我需要的:

publicKey: <SecKeyRef algorithm id: 1, key type: RSAPublicKey, version: 3, block size: 2048 bits, exponent: {hex: 10001, decimal: 65537}, modulus: B2A7BD90C909F8084AD5B34040ABDAF7D1A6AFBADB35F3B6AB5CDDAB473449B0F175DEA32A7476F339D98F4AB3716AA2C1476D4009A80574B984DDFA1EF1A2550E48C46791CEFBFC39EF281049AA74E4C734C3B2A7B3F621B8A41F8B6689C4978696690D4EF9FFF0F90DB85C8ECBCF721FB7652AD7B337880A09D97EA736008C3ADBB72223F18C522C0C0889B05122561042D8637D1CBEF8F9F5AE88CDC43E411AA217E2A81C2D812B46D01C3BDC2799DFF3EAD46BB092A566E18EE94F63C4690ECE806B993FDDAC3159BE2098C2428F24969C109E221D8F066BEE3530848DE328D888B4C7E701435EACB116F97BB77B9379EF818B4D280890262EE678B92705, addr: 0x144841a00>

但我不知道如何导出密钥,以便将其发送到我的服务器以供在那里使用。

据我了解。 SecKey 存储在 Keychain 中,是一个指向它的指针,块大小是密钥在内存中的长度。所以理论上我可以将它提取为 NSData ,然后将其转换为我的服务器可以读取的内容。理论上我认为这会奏效,但我在实践中试图做到这一点却碰壁了。我们将不胜感激所有帮助。

【问题讨论】:

    标签: swift ios8 public-key-encryption


    【解决方案1】:

    SecItemCopyMatching 适合你:

    var dataPtr:Unmanaged<AnyObject>?
    let query: [String:AnyObject] = [
        kSecClass: kSecClassKey,
        kSecAttrApplicationTag: "com.example.site.public",
        kSecReturnData: kCFBooleanTrue
    ]
    let qResult = SecItemCopyMatching(query, &dataPtr)
    
    // error handling with `qResult` ...
    
    let publicKeyData = dataPtr!.takeRetainedValue() as NSData
    
    // convert to Base64 string
    let base64PublicKey = publicKeyData.base64EncodedStringWithOptions(nil)
    

    斯威夫特 4:

    var dataPtr:CFTypeRef?
    let query: [String: Any] = [
        kSecClass as String: kSecClassKey,
        kSecAttrApplicationTag as String: "com.example.site.public",
        kSecReturnData as String: true
    ]
    
    let qResult = SecItemCopyMatching(query as CFDictionary, &dataPtr)
    
    // error handling with `qResult` ...
    
    let data = dataPtr as! Data
    let base64PublicKey = data.base64EncodedString()
    

    注意数据的大小是270,和key的块大小不一样。见this question on the crypto.stackexchange.com

    【讨论】:

    • 这看起来很有希望,谢谢。我会尽快将其标记为正确的。快速跟进。我看到它是 NSData,我如何将其转换为可以发送到它可以理解的 Web 服务器的东西?谢谢。
    • 这取决于服务器接受什么。通常,使用 HTTP 发送到服务器时,使用 publicKeyData.base64EncodedStringWithOptions(nil) 编码为 base64 字符串,并使用 NSJSONSerialization 序列化为 JSON。
    • 所以即使我们将 PublicKeyData 作为 NSData 我仍然可以使用 base64EncodeString 吗?
    • 谢谢@rintaro!就是这样!
    • 我无法将 Unmanaged 类型的值转换为预期的参数类型 AnyObjects 这是 XCode 错误我该如何解决??
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 2015-05-02
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多