获取SecKey的字符串表示形式

时间:2017-10-23 13:33:46

标签: swift public-key-encryption

修改添加了所需请求的精简版。

我试图在Swift 4中创建一个MacOs应用程序。此应用程序与需要RSA加密的API进行通信。

谷歌没有给出可以解释如何做到这一点的结果。 Apple关于这个主题的文档非常广泛(https://developer.apple.com/library/content/documentation/Security/Conceptual/CertKeyTrustProgGuide/KeyRead.html#//apple_ref/doc/uid/TP40001358-CH222-SW2),但仍然不是我需要的。

SecKeyCopyExternalRepresentation函数给出了一个Data对象 无法转换为String。文档说它是PCKS#1的回应,但我无法解决。

我已经尝试了很多东西,包括下面的内容,但是我无法让它发挥作用。

func externalRepresentation(_ key: SecKey) -> String? {
    var error: Unmanaged<CFError>?

    guard let data = SecKeyCopyExternalRepresentation(key, &error) as Data? else {
        return nil
    }

    return data.base64EncodedString()
}

请求必须如下: Request

这在Swift中是否可能?

2 个答案:

答案 0 :(得分:1)

将二进制blob(如证书或RSA密钥)编码为字符串的常规方法是使用base64编码。您可以使用函数base64EncodedString(options:)轻松地将Data转换为base64。即。

let myString = myData.base64EncodedString()

这是否正是您对此应用程序所需的内容很难说清楚,因为您的问题并没有提供太多背景信息。

查看屏幕截图以及base64编码的字符串,需要页眉和页脚。数据结构中大多数明显随机的字母都是base64字符串(JSON转换使用\n编码换行符,而其他东西则使反斜杠加倍。因此,您的最后一步是在字符串前面添加-----BEGIN PUBLIC KEY-----和新行,广告附加一个新行并-----END PUBLIC KEY-----

还有一件事:您可以使用Data.init?((base64Encoded base64String:,options:)轻松地从base64字符串中恢复原始数据。即。

guard let myDataCopy = Data(base64Encoded: myString)
else { fatalError("the string was not really base64") }

答案 1 :(得分:0)

SecKeyCopyExternalRepresentation返回RSA密钥的PKCS#1格式的数据。 RSA公钥PEM文件如下所示

-----BEGIN RSA PUBLIC KEY-----
BASE64 ENCODED DATA
-----END RSA PUBLIC KEY-----

在base64编码的数据中,存在以下DER结构:

RSAPublicKey ::= SEQUENCE {
    modulus           INTEGER,  -- n
    publicExponent    INTEGER   -- e
}

RSA密钥的PKCS#1格式应由适当的“预编码” ASN.1二进制数据结构作为前缀。请参考以下示例中的pemPrefixBuffer:

        // creating client public and private key
        var publicKeySec, privateKeySec: SecKey?
        var error: Unmanaged<CFError>?
        let keyattribute = [
            kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
            kSecAttrKeySizeInBits as String : 1024,
            kSecAttrIsPermanent as String: false
            ] as CFDictionary
        SecKeyGeneratePair(keyattribute, &publicKeySec, &privateKeySec)
        
        // client public key to pem string
        let keyData = SecKeyCopyExternalRepresentation(publicKeySec!, &error)
        let data = keyData! as Data
        let pemPrefixBuffer :[UInt8] = [
            0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a,
            0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
            0x05, 0x00, 0x03, 0x81, 0x8d, 0x00
        ]
        var finalPemData = Data(bytes: pemPrefixBuffer as [UInt8], count: pemPrefixBuffer.count)
        finalPemData.append(data)
        let finalPemString = finalPemData.base64EncodedString(options: .lineLength64Characters)
        let clientPublicKeyString = "-----BEGIN PUBLIC KEY-----\r\n\(finalPemString)\r\n-----END PUBLIC KEY-----\r\n"

现在,您可以将clientPublicKeyString发送到服务器,并期待使用PEM编码的RSA公钥。