Unable to create SecKey from serverPublic key

I am unable to create SecKey from serverPublic key. I get the below error

Error Domain=NSOSStatusErrorDomain Code=-50 "EC public key creation from data failed" UserInfo={numberOfErrorsDeep=0, NSDescription=EC public key creation from data failed}

My code looks like this so far. Not sure what is going wrong.

let attributes: [String: Any] = [
                    kSecAttrKeyType as String: kSecAttrKeyTypeEC,
                    kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
                    kSecAttrKeySizeInBits as String: 256
                ]
                
                let serverPublicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGcpMOdqpgCt3Lhvy8pqBcPgQdKcj646CqJWArdcvkaTZfIGADRsk6TkKuvcHVE+excJ2fKlZDLLRt1vy8n7xww=="
                guard let serverPublicKeyData = Data(base64Encoded: serverPublicKey) else { return }
                                
                var error: Unmanaged<CFError>?
                guard let serverPublickeySec = SecKeyCreateWithData(serverPublicKeyData as CFData, attributes as CFDictionary, &error) else {
                    throw error!.takeRetainedValue() as Error
                }
Answered by DTS Engineer in 802857022

I have two posts that I point folks at:

Using the techniques from those posts, I dumped your example key:

% dumpasn1 -p tmp.dat   
SEQUENCE {
  SEQUENCE {
    OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
    OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7)
    }
  BIT STRING
    04 19 CA 4C 39 DA A9 80 2B 77 2E 1B F2 F2 9A 81
    70 F8 10 74 A7 23 EB 8E 82 A8 95 80 AD D7 2F 91
    A4 D9 7C 81 80 0D 1B 24 E9 39 0A BA F7 07 54 4F
    9E C5 C2 76 7C A9 59 0C B2 D1 B7 5B F2 F2 7E F1
    C3
  }

This has the SubjectPublicKeyInfo, meaning you can’t pass it directly to SecKeyCreateWithData. If you can use Apple CryptoKit, that’s the easiest path forward here:

import Foundation
import CryptoKit

func test() throws {
    let serverPublicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGcpMOdqpgCt3Lhvy8pqBcPgQdKcj646CqJWArdcvkaTZfIGADRsk6TkKuvcHVE+excJ2fKlZDLLRt1vy8n7xww=="
    guard let serverPublicKeyData = Data(base64Encoded: serverPublicKey) else { return }

    let key = try P256.Signing.PublicKey(derRepresentation: serverPublicKeyData)
    print(key)
    // PublicKey(impl: …)
}

try test()

If you absolutely need to a SecKey, you can bounce through CryptoKit:

… key is as above …

let key2 = try secCall { SecKeyCreateWithData(key.x963Representation as NSData, [
    kSecAttrKeyType as String: kSecAttrKeyTypeEC,
    kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
    kSecAttrKeySizeInBits as String: 256
] as NSDictionary, $0) }

print(key2)
// <SecKeyRef curve type: kSecECCurveSecp256r1, … >

ps These use the helpers from here.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I have two posts that I point folks at:

Using the techniques from those posts, I dumped your example key:

% dumpasn1 -p tmp.dat   
SEQUENCE {
  SEQUENCE {
    OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1)
    OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7)
    }
  BIT STRING
    04 19 CA 4C 39 DA A9 80 2B 77 2E 1B F2 F2 9A 81
    70 F8 10 74 A7 23 EB 8E 82 A8 95 80 AD D7 2F 91
    A4 D9 7C 81 80 0D 1B 24 E9 39 0A BA F7 07 54 4F
    9E C5 C2 76 7C A9 59 0C B2 D1 B7 5B F2 F2 7E F1
    C3
  }

This has the SubjectPublicKeyInfo, meaning you can’t pass it directly to SecKeyCreateWithData. If you can use Apple CryptoKit, that’s the easiest path forward here:

import Foundation
import CryptoKit

func test() throws {
    let serverPublicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGcpMOdqpgCt3Lhvy8pqBcPgQdKcj646CqJWArdcvkaTZfIGADRsk6TkKuvcHVE+excJ2fKlZDLLRt1vy8n7xww=="
    guard let serverPublicKeyData = Data(base64Encoded: serverPublicKey) else { return }

    let key = try P256.Signing.PublicKey(derRepresentation: serverPublicKeyData)
    print(key)
    // PublicKey(impl: …)
}

try test()

If you absolutely need to a SecKey, you can bounce through CryptoKit:

… key is as above …

let key2 = try secCall { SecKeyCreateWithData(key.x963Representation as NSData, [
    kSecAttrKeyType as String: kSecAttrKeyTypeEC,
    kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
    kSecAttrKeySizeInBits as String: 256
] as NSDictionary, $0) }

print(key2)
// <SecKeyRef curve type: kSecECCurveSecp256r1, … >

ps These use the helpers from here.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Unable to create SecKey from serverPublic key
 
 
Q