To work with OpenSSL, you need subject public key info (SPKI), either DER or PEM format.
SPKI contains essential information, for example, key.type, key.parameters, key.value.
SecKeyCopyExternalRepresentation only returns raw key binary which is only key.value part.
You have to create SPKI from that key.value. The normal way to do this is to read https://www.rfc-editor.org/rfc/rfc5480, and encode ASN.1 structure to binary-encoded DER format.
But here is a shortcut.
Secure Enclave only supports one key type, 256-bit EC key secp256r1 (equivalent to prime256v1 in OpenSSL).
The SPKI in DER format is a binary encoded data, for example,
3059301306072a8648ce3d020106082a8648ce3d03010703420004fad2e70b0f70f0bf80d7f7cbe8dd4237ca9e59357647e7a7cb90d71a71f6b57869069bcdd24272932c6bdd51895fe2180ea0748c737adecc1cefa3a02022164d
It always consist of two parts
fixed schema header 3059301306072a8648ce3d020106082a8648ce3d030107034200
raw key value 04.......
You can create SPKI by combining these two parts.
spki = fixed_schema_header + SecKeyCopyExternalRepresentation(...)
func createSubjectPublicKeyInfo(rawPublicKeyData: Data) -> Data {
let secp256r1Header = Data(bytes: [
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00
])
return secp256r1Header + rawPublicKeyData
}
// Usage
let rawPublicKeyData = SecKeyCopyExternalRepresentation(...)!
let publicKeyDER = createSubjectPublicKeyInfo(rawPublicKeyData: rawPublicKeyData)
write(publicKeyDER, to: "public_key.der")
// Test with OpenSSL
// openssl ec -pubin -in public_key.der -text -inform der