How to create PublicKey from PEM?

I'm pretty new to RSA Keys and Certificates and all of that. So I'm getting a PEM File from a network request, I understand the PEM file is basically the certificate without header and footer, so essentially I have a string. I need to create a PublicKey from that in order to Encrypt some text, but I think I'm doing something wrong. This is my code so far, I have talked to other teams (Android) and when they print out the Encrypted Data, they are getting a regular String and I'm getting lots of weird characters. Thanks in advance guys! (:

func encryptBase64(text: String, certificateStr: String) throws -> Data {
    let encryptionError = EncrpytionError(message: "There has been an issue with encryption")

    guard
        let certData = Data(base64Encoded: certificateStr),
        let certificate = SecCertificateCreateWithData(nil, certData as CFData),
        let publicKey = SecCertificateCopyKey(certificate)
    else {
        throw encryptionError
    }

    let algorithm: SecKeyAlgorithm = .rsaEncryptionOAEPSHA256AESGCM

    guard SecKeyIsAlgorithmSupported(publicKey, .encrypt, algorithm) else {
        throw encryptionError
    }
    guard let cipherText = SecKeyCreateEncryptedData(
        publicKey,
        algorithm,
        text.data(using: .utf8)! as CFData, nil)
    else {
        throw encryptionError
    }
    return cipherText as Data
}

And when I try to print cipherText as a String using

let encryptedString = String(decoding: encryptedData, as: UTF8.self)

I just get this weird thing:

"D�aj�\\m꒤h,�A�{��8�~�\nY\u0003F�Cˤ�@��\"�\u0018�\u0007\u001fX@VC�U_��E\u0005dž1���X��\/4Px��P\u0016�8}% ��<��@�I_�K\u000e�\bR*�� ���斋�7,�%���F^q�\u0000\\�'�ZTD\u0013Q�_\u0010\u001f>i]&��B���@1\u0006\b��E\u0004�F���yS\u0013�3����SB)��m\u0017%��5ʲ����s\u0003��r�&�?�8b��W@\u001e��؞ۡ��8�s~��ӹ�u\"�2��U�&\b�3XV���˔Y��xt[\fm&P:\\�\f� y��6jy"

Android team is doing something like this using Kotlin:

private fun extractPublicKey(certificateString: String): PublicKey {
            val encodedCertificateBytes = certificateString.toByteArray()
            val decodedCertificateBytes = Base64.decode(encodedCertificateBytes, Base64.DEFAULT)
            val inStream = decodedCertificateBytes.inputStream()
            val certificateFactory = CertificateFactory.getInstance("X.509")
            val certificate = certificateFactory.generateCertificate(inStream)
            inStream.close()
            return certificate.publicKey
}

Replies

I’m going to start you off with these two posts:

If you can’t figure things out from there, post back here and include an example of the data you’re starting with (certificateStr in your code snippet).

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"