Thanks for the focused test example. The problem here is that your input data is for a public key and you’re trying to import it as a private key.
Consider the bit string from the ASN.1 dump from my previous post:
$ xxd -p tmp.dat
041faef0d68b3127580cc1d87c76aff372bc804ee8a1810cbef0919a0a9f
3e129b8fb53f57610fd7d51216ec768abd44a11ff1dbf34ce64c682fe22e
a64529237a
If you convert it to Base64 you get this:
$ base64 tmp.dat
BB+u8NaLMSdYDMHYfHav83K8gE7ooYEMvvCRmgqfPhKbj7U/V2EP19USFux2ir1EoR/x2/NM5kxoL+IupkUpI3o=
I plugged that into your test snippet and change it to import a public key (
kSecAttrKeyClassPublic
), like so:
import Foundation
func test(b64: String) {
guard let data = Data(base64Encoded: b64, options: [.ignoreUnknownCharacters]) else {fatalError("Unknown Format")}
var error: Unmanaged<CFError>? = nil
let params = [kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyClass: kSecAttrKeyClassPublic] as CFDictionary
if let key = SecKeyCreateWithData(data as CFData, params, &error) {
print("Key", key)
} else if let e = error {
print("Error", e)
} else {
print("Error")
}
}
test(b64: "BB+u8NaLMSdYDMHYfHav83K8gE7ooYEMvvCRmgqfPhKbj7U/V2EP19USFux2ir1EoR/x2/NM5kxoL+IupkUpI3o=")
It successfully imports the key, printing:
Key <SecKeyRef curve type: kSecECCurveSecp256r1, algorithm id: 3, key type: ECPublicKey, version: 4, block size: 256 bits, y: 8FB53F57610FD7D51216EC768ABD44A11FF1DBF34CE64C682FE22EA64529237A, x: 1FAEF0D68B3127580CC1D87C76AFF372BC804EE8A1810CBEF0919A0A9F3E129B, addr: 0x101b5d4f0>
To further explore this I wrote a tiny test project to generate a new, random EC p256r1 key pair and then dumped the private and public key bytes:
let privateKey = SecKeyCreateRandomKey([
kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
kSecAttrKeySizeInBits: 256
] as NSDictionary, nil)!
let publicKey = SecKeyCopyPublicKey(privateKey)!
let privateData = SecKeyCopyExternalRepresentation(privateKey, nil)! as Data
let publicData = SecKeyCopyExternalRepresentation(publicKey, nil)! as Data
print("private: ", privateData as NSData)
print("public: ", publicData as NSData)
Here’s an example of its output:
private: <04a21f94 07831a37 d9ba294c 2b9c16db 599496de 8a44e909 fd8b6fba f947ed51 c775152f 806af756 9409f18e 87261847 54d19e9a 63ccfd49 af2f7c1f 642da582 84c682d0 e2ac6c42 dcac9417 b31cdccc 2962926d fe088ff3 1dfc3c60 e19c02fb b9>
public: <04a21f94 07831a37 d9ba294c 2b9c16db 599496de 8a44e909 fd8b6fba f947ed51 c775152f 806af756 9409f18e 87261847 54d19e9a 63ccfd49 af2f7c1f 642da582 84>
Note how the public key is 65 bytes long, a length that matches the key in your example, but the private key is longer (97 bytes).
I’m not sure why your PEM is labelled as a private key; you’ll need to have a chat with whoever generated it.
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"