Why does the following code generate a public key that can't be parsed by openssl?
import Security
import CryptoKit
func generateKeys() throws -> (privateKey: SecKey, publicKey: SecKey) {
let query: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits as String: 256,
kSecAttrIsPermanent as String: false
]
var error: Unmanaged<CFError>?
guard let privateKey = SecKeyCreateRandomKey(query as CFDictionary, &error) else {
throw error!.takeRetainedValue()
}
let publicKey = SecKeyCopyPublicKey(privateKey)!
return (privateKey, publicKey)
}
extension SecKey {
func exportBase64EncodedKey() -> String {
var error: Unmanaged<CFError>?
guard let data = SecKeyCopyExternalRepresentation(self, &error) else {
fatalError("Failed to export key: \(error!.takeRetainedValue())")
}
return (data as Data).base64EncodedString(options: [.lineLength64Characters])
}
}
func printPublicKey() {
let keyPair = try! generateKeys()
let encodedPublicKey = keyPair.publicKey.exportBase64EncodedKey()
var header = "-----BEGIN PUBLIC KEY-----"
var footer = "-----END PUBLIC KEY-----"
var pemKey = "\(header)\n\(encodedPublicKey)\n\(footer)\n"
print(pemKey)
}
printPublicKey()
when parsing the key I get this:
openssl pkey -pubin -in new_public_key.pem -text -noout
Could not find private key of Public Key from new_public_key.pem
404278EC01000000:error:1E08010C:DECODER routines:OSSL_DECODER_from_bio:unsupported:crypto/encode_decode/decoder_lib.c:102:No supported data to decode.
Replacing kSecAttrKeyTypeECSECPrimeRandom
with kSecAttrKeyTypeRSA
and a bigger key size (e.g. 2048) gives me a working public key that can be parsed by Openssl.
Thanks!
Why does the following code generate a public key that can't be parsed by openssl?
Because SecKeyCopyExternalRepresentation
returns raw key bytes and openssl
is expected the key to be wrapped, probably in a SubjectPublicKeyInfo
structure. I recommend that you have a read through On Cryptographic Keys Formats.
If your goal is to get a PEM then the easiest option is to feed the raw key bytes in Apple CryptoKit (see here) and then get the pemRepresentation
property.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"