I've been reading previous threads such as this about how to import openssl generated keys using SecKeyCreateWithData but always get the error Code=-50 "EC private key creation from data failed". I understand that SecKeyCreateWithData doesn't allow the standard headers that openssl generates, but even after converting the bit string section to a binary file, it refuses to load.
This is the command I use to generate the key:
openssl ecparam -name prime256v1 -genkey -noout -out openssl.key -outform der
Using dumpasn1:
$ ~/Desktop/dumpasn1 -w76 openssl.key
0 119: SEQUENCE {
2 1: INTEGER 1
5 32: OCTET STRING
: 67 BF 75 38 C7 14 38 88 4C DD BC 91 A5 5C 88 10
: DE 0C 6F EE A7 2B 85 75 19 EC 71 1D 91 BD FD E3
39 10: [0] {
41 8: OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7)
: }
51 68: [1] {
53 66: BIT STRING
: 04 5A C4 BB DE 43 15 25 9E E2 A3 CD D8 80 0E 12
: 57 24 0D 68 BD 22 61 57 D9 87 F8 E2 16 DD 8C 02
: AD 73 4F D0 69 6F F0 61 0D FD FB 4D EB F1 45 C0
: AB D4 46 82 B6 DB 69 62 8F C9 7C C9 07 09 0C 91
: 91
: }
: }
If I trim off the headers:
$ dd if=openssl.key of=stripped.openssl.key skip=56 bs=1
65+0 records in
65+0 records out
65 bytes transferred in 0.000320 secs (203001 bytes/sec)
$ hexdump -Cv stripped.openssl.key
00000000 04 5a c4 bb de 43 15 25 9e e2 a3 cd d8 80 0e 12 |.Z...C.%........|
00000010 57 24 0d 68 bd 22 61 57 d9 87 f8 e2 16 dd 8c 02 |W$.h."aW........|
00000020 ad 73 4f d0 69 6f f0 61 0d fd fb 4d eb f1 45 c0 |.sO.io.a...M..E.|
00000030 ab d4 46 82 b6 db 69 62 8f c9 7c c9 07 09 0c 91 |..F...ib..|.....|
00000040 91 |.|
00000041
It's 65 bytes beginning with 04, which I believe it just the keydata. This refuses to load on iOS with the error:
var error: Unmanaged?
guard let key = SecKeyCreateWithData(privateKey as CFData,
[kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeyClass: kSecAttrKeyClassPrivate,
kSecAttrKeySizeInBits: 256] as CFDictionary,
&error)
key length: 65
failed - Failed to create key: Unmanaged(_value: Error Domain=NSOSStatusErrorDomain Code=-50 "EC private key creation from data failed" UserInfo={NSDescription=EC private key creation from data failed})
However, it will load as a public key which I don't understand.
I tried creating a key in iOS then saving it as data and it generates a larger size (97 vs 65) but it will succesfully load.
$ hexdump -Cv ios.private.key
00000000 04 6b 17 c3 46 32 db 10 02 9a 2b 02 de 53 89 c3 |.k..F2....+..S..|
00000010 87 71 d3 bf b6 1a 64 c0 0e e1 35 6e 1c 9f af 5f |.q....d...5n..._|
00000020 70 d2 05 ba fc 4e fb 5a e2 93 6a 68 12 b1 18 a8 |p....N.Z..jh....|
00000030 c3 f1 2a db aa 77 a1 e0 57 bc d9 23 6c a4 82 c7 |..*..w..W..#l...|
00000040 75 a9 d0 e0 01 76 6c de 8d f0 22 64 a0 4e 06 bf |u....vl..."d.N..|
00000050 c3 0e b1 4d 45 3e fc 9f f1 a4 4b e3 85 e0 0f 07 |...ME>....K.....|
00000060 bd |.|
00000061
I just want to understand what these extra bytes are and how to get a openssl-generated key to load in iOS.
Thanks
In
<Security.framework/SecKey.h>
you’ll see this comment:
The requested data format depend on the type of key (kSecAttrKeyType) being created:
* kSecAttrKeyTypeRSA PKCS#1 format, public key can be also in x509 public key format
* kSecAttrKeyTypeECSECPrimeRandom ANSI X9.63 format (04 || X || Y [ || K])
Look at the last line, which describes the EC key format. The
K
item is in square brackets, indicating it’s optional. This is the difference between a public key (without
K
) and a private key (with
K
).
I don’t know what spec the OpenSSL key conforms to — I don’t have time tonight to look up the details — but it seems that it stores this
K
value in first
OCTET STRING
. That is, if you take the 67 BF 75 38 … 91 BD FD E3 bytes and append it to 04 5A C4 BB … 09 0C 91 91 bytes, you end up with 97 bytes that import correctly.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"