在Swift中从服务器获取公钥字符串生成安全密钥

9

我希望使用RSA加密数据,我已经尝试在我的代码中生成密钥并且它可以工作。但是我实际上需要从服务器获取公钥字符串,然后将其用作Seckey以便我可以使用它来使用RSA加密数据, 我尝试了这段代码:

//KeyString is the string of the key from server
let KeyData = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData!


    var cert : Unmanaged<SecCertificateRef>!;
    var  policy : Unmanaged<SecPolicy>!;
    cert = SecCertificateCreateWithData(kCFAllocatorDefault, KeyData);
    policy = SecPolicyCreateBasicX509();
    var status : OSStatus = noErr
    var trust: SecTrust?
    var certArray : [Unmanaged<SecCertificateRef>!] = [cert];
    var certArrayPointer = UnsafeMutablePointer<UnsafePointer<Void>>(certArray)
    status = SecTrustCreateWithCertificates(cert, policy, trust);
    let publicKey: SecKeyRef = SecTrustCopyPublicKey(trust!).takeUnretainedValue()

我无法运行这段代码,因为SecTrustCreateWithCertificates方法期望证书作为任意对象!我不知道如何解决这个问题,如果解决了这个问题,我就可以得到SecKey。

我从这个objective-c答案中获得了上面的代码。

所以,如果有人能帮我找到正确的代码来解决这个问题,我将非常感激:)

3个回答

17

对于Mac电脑:

let pubKey = "-----BEGIN PUBLIC KEY-----MIICIjANBgAgK.......InbFk1FkucQqruMyUCAwEAAQ==-----END PUBLIC KEY-----"
let pubKeyData = pubKey.dataUsingEncoding(NSASCIIStringEncoding)
var error: Unmanaged<CFErrorRef>?
let secKey = SecKeyCreateFromData(NSDictionary(), pubKeyData!, &error)

pubKey是您公钥的字符串表示形式。如果您不知道自己的公钥,可以使用以下命令从私钥推导出它:

openssl rsa -in server.key -pubout  > mykey.pub

服务器密钥存储在名为 server.key 的文件中,该文件的第一行包含 -----BEGIN RSA PRIVATE KEY-----

iOS:

这有点复杂。 你需要一个 der 文件。它是您证书的二进制表示。 如果您需要转换现有证书,可以使用以下命令进行转换:

 openssl x509 -outform der -in file.crt|pem -out mycert.der

.crt.pem文件的第一行应包含-----BEGIN CERTIFICATE-----

der文件放在您的捆绑软件中并执行以下操作:

let certificateData = NSData(contentsOfURL:NSBundle.mainBundle().URLForResource("mycert", withExtension: "der")!)

let certificate = SecCertificateCreateWithData(nil, certificateData!)

var trust: SecTrustRef?

let policy = SecPolicyCreateBasicX509()
let status = SecTrustCreateWithCertificates(certificate!, policy, &trust)

if status == errSecSuccess {
    let key = SecTrustCopyPublicKey(trust!)!;
}

太好了!Key现在包含您公钥的SecKey表示。祝贺您完成指纹识别。


解释一下 pubKey 会让答案更有用。 - zaph
有用的指令:将 .cer 转换为 .pem openssl x509 -in NAME.cer -inform der -out NAME.pem将 .pem 转换为 .der openssl x509 -outform der -in NAME.pem -out NAME.der - Husam
1
这是否意味着我们只能使用der文件,在iOS中不能使用pem密钥? - DàChún
12
这并没有回答关于“从服务器发送的公钥字符串获取SecKey”的问题。 - Sameer Bhide
1
你可以使用PEM密钥,但必须去掉头和尾,并使用Data(base64Encoded: base64string)解码base64字符串,这将给你数据,你可以传递给SecCertificateCreateWithData。参见:https://dev59.com/vWkv5IYBdhLWcg3wdQnm - Koen.
显示剩余2条评论

0

这是我是如何做到的:

let cert = SecCertificateCreateWithData(kCFAllocatorDefault, certData)?.takeRetainedValue()

if cert != nil {
    var trust: Unmanaged<SecTrust>?

    let policy = SecPolicyCreateBasicX509().takeRetainedValue()
    let status = SecTrustCreateWithCertificates(cert, policy, &trust)

    if status == errSecSuccess {
        let trustRef = trust!.takeRetainedValue()
        let key = SecTrustCopyPublicKey(trustRef)!.takeRetainedValue();
    }
}

这个方法是可行的,但你需要确保传递给 SecCertificateCreateWithData() 的是一个 DER 编码的证书,而不仅仅是一个 DER 编码的密钥。你需要使用由服务器私钥签名的证书来获取相关联的公钥。


0

我使用了Alamofire:

private static func publicKeyForCertificate(certificate: SecCertificate) -> SecKey? {
    var publicKey: SecKey?
    var trust: Unmanaged<SecTrust>?

    let policy = SecPolicyCreateBasicX509().takeRetainedValue()
    let status = SecTrustCreateWithCertificates(certificate, policy, &trust)

    if status == errSecSuccess {
        let trustRef = trust!.takeRetainedValue()
        publicKey = SecTrustCopyPublicKey(trustRef)!.takeRetainedValue()

    }
    return publicKey

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接