I'm trying to create a Private/Public key pair inside the SecureEnclave with CryptoKit and then save the reference to the private key in the KeyChain for further usage. The key generation works totally fine:

let accessControl = SecAccessControlCreateWithFlags(
   kCFAllocatorDefault,
   kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
   [.privateKeyUsage],
    nil
)!
let privateKey = try SecureEnclave.P256.Signing.PrivateKey(accessControl: accessControl)
// Describe the key.
let attributes = [
   kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
   kSecAttrKeyClass: kSecAttrKeyClassPrivate
] as [String: Any]

But when I'm trying to convert the key I've just created into the SecKey to store it in the Keychain later:

// Get a SecKey representation.
var error: Unmanaged<CFError>?
guard let secKey = SecKeyCreateWithData(key.dataRepresentation as CFData, attributes as CFDictionary, nil) else {
   throw error!.takeRetainedValue()
}

It fails with an error:

The operation couldn’t be completed. (OSStatus error -50 - EC private key creation from data failed)

On the other hand, when I remove the SecureEnclave element, and use the x963Representation I'm capable of converting the private key into the SecKey object:

let privateKey = P256.Signing.PrivateKey()
guard let secKey = SecKeyCreateWithData(privateKey.x963Representation as CFData, attributes as CFDictionary, nil) else {
   throw error!.takeRetainedValue()
}

Any ideas on why this is happening or how can I fix this?

1

There are 1 best solutions below

0
On BEST ANSWER

Not all keys can be stored (directly) into the Keychain as described in the documentation. To resolve this, you can store raw Data as generic password in the Keychain. It's a bit unfortunate for the SecureEnclave keys.

In addition, the .dataRepresentation of the Secure Enclave private key is not something the Security framework understands. Secure Enclave keys are not intended to be extracted (and as far as I know cannot be extracted at all). The blob you extract is a container that the same enclave can use to reconstruct the private key. Using the same data on another iPhone will not recreate the key.

I'm not sure if storing this blob as file on the device is a security risk. So I suggest you take a look at the previously mentioned documentation and use the GenericPasswordConvertible example.