I have a private/public key pair generated and stored inside Secure Enclave.
It is 256-bit elliptic curve key. (The only key type that can be stored in Secure Enclave).
I use SecKeyCreateWithData
and SecKeyCopyExternalRepresentation
to import/export the public key between iOS devices, and it works.
However, the exported key doesn't seem to work with OpenSSL.
Because it always show 'unable to load Key'
on this command.
openssl ec -pubin -in public_key_file -text
What's the way to export the key ? So I can use it with OpenSSL.
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://tools.ietf.org/html/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