iosswiftrsapublic-key-exchange

How to convert server's public key into SecKey format to encrypt data using RSA?


I want to convert the server's public key (base64encoded string) into SecKey format to encrypt data using RSA but fail to convert the string to SecKey.

Please let me know if it is necessary to convert the key into SecKey format, if yes then please help me out.

below is my code.

func publicKeyFromString(_ keyString: String) -> SecKey? {
    guard let publicKeyString = keyString.base64Decoded() else { return nil }
    let publicKeyStringWithoutHeaders = publicKeyString.replacingOccurrences(of: "-----BEGIN RSA PUBLIC KEY-----\n", with: "").replacingOccurrences(of: "\n-----END RSA PUBLIC KEY-----\n", with: "")
    guard let publicKeyData = publicKeyStringWithoutHeaders.utf8Data else {
        print("Failed to decode the public key string.")
        return nil
    }
    let keyDict: [NSString: AnyObject] = [
        kSecAttrKeyType: kSecAttrKeyTypeRSA,
        kSecAttrKeyClass: kSecAttrKeyClassPublic,
        kSecAttrKeySizeInBits: 2048 as AnyObject
    ]
    var error: Unmanaged<CFError>?
    guard let publicKey = SecKeyCreateWithData(publicKeyData as CFData, keyDict as CFDictionary, &error) else {
        print("Failed to create public key:", error!.takeRetainedValue())
        return nil
    }
    return publicKey
}

Use:

let serverPublicKey = "LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JSUJDZ0tDQVFFQWs0eE5pYjQ2eW9KL2l2c0s0SEhwcTlKYmQ4SGdzZlJTSG0yTHhxQWZRdVdaV1I3NVVrMWcKcjFCekluWXkxZFFYOVczanVOMFpKdXcvd3hSSTI2VFJRdWxWeXVHQk9aSER2Nk00aVRRNXlWNitpd1kxdlVDNgp4UFZLS3JYazFzNm9TUWVpSUFiangzMmIzRndBK1E3MkszVEJ2UUJRbUtuOExvaVR0UFJOMUo1Y3BWbEYzeXVjCnlDazlTQjR0ejdLQ2JSUHVScEsxclRyV2hmcmFxeVB3RGNvMVR6Vlo0K095d0hsbjFRZE9FL2xQQ1R5aGVKVUEKK1dsSmtRd00vRXdmVE1SekkrZTdwU2d2c3hEejFLZHpUakp6SjBzcXVUSVg2UDZHREhKelBCRWN5cDVNUlhSMwpuZXpUWDF2dmNlTGJVQW9hKzBzRmlCMU9sbVJMRTI2MGJ3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K"
if let key = RSAHelper.publicKeyFromString(serverPublicKey) {
    print(key)
}

I found error [seckey] SecKeyCreate init(RSAPublicKey) failed: -50. Please let me know the process.


Solution

  • Here is the working code for convert String PEM key to SecKey,

        class func publicKeyFromString(_ keyString: String) -> SecKey? {
        guard let publicKeyString = keyString.base64Decoded() else { return nil }
        let publicKeyStringWithoutHeaders = publicKeyString.replacingOccurrences(of: "-----BEGIN RSA PUBLIC KEY-----\n", with: "").replacingOccurrences(of: "\n-----END RSA PUBLIC KEY-----\n", with: "")
    
        let publicKeyData = NSData(base64Encoded: publicKeyStringWithoutHeaders, options:NSData.Base64DecodingOptions.ignoreUnknownCharacters)!
    
        let keyDict: [NSString: AnyObject] = [
            kSecAttrKeyType: kSecAttrKeyTypeRSA,
            kSecAttrKeyClass: kSecAttrKeyClassPublic,
            kSecAttrKeySizeInBits: 2048 as AnyObject
        ]
        var error: Unmanaged<CFError>?
        guard let publicKey = SecKeyCreateWithData(publicKeyData as CFData, keyDict as CFDictionary, &error) else {
            print("Failed to create public key:", error!.takeRetainedValue())
            return nil
        }
        return publicKey
    }