Conversion from Base64 Public Key Data to SecKey and convert back from SecKey to Public Key Data are not the same. How can i resolve this?

I am trying to convert publicKeyFromDongleData to SecKey, then perform some tasks. After that, I want to convert SecKey to b64 String. I am assuming that publicKeyFromDongleData and b64 string will be the same. But, surprisingly, they are not the same. How can i resolve the issue? Is there any way around?

My goal is to retain the public key before and after converting the same.

let publicKeyFromDongleData = Data.init(base64Encoded: publicKeyFromDongle)

        guard let publicKeySecKey = SecKeyCreateWithData(publicKeyFromDongleData! as CFData, keyDict as CFDictionary, &error) else {

                        print("Failed to create public key:", error!.takeRetainedValue())

                        return nil

                    }
        //var error:Unmanaged<CFError>?
        if let cfdata = SecKeyCopyExternalRepresentation(publicKeySecKey, &error) {
           let data:Data = cfdata as Data
           let b64Key = data.base64EncodedString()
           print("after : \n")
           print(b64Key)
        }

Replies

This is almost certainly caused by the difference between the RSAPublicKey structure and the SubjectPublicKeyInfo structure. See On Cryptographic Key Formats for a definition of those terms. For RSA keys, SecKeyCreateWithData accepts both formats but SecKeyCopyExternalRepresentation always generates RSAPublicKey.

Share and Enjoy

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

Through experimentation I have worked out that exporting the public key as follows will generate a SubjectPublicKeyInfo:

        err = SecItemExport(keyref, kSecFormatOpenSSL, 0, NULL, &der);

Sure. The main drawback with this approach is that SecItemExport is only available on macOS.

Share and Enjoy

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