Converting Secure Enclave protected SecKey to SecureEnclave.P256.Signing.PrivateKey

Is it possible?

The original key was generated and stored in the Keychain using the following code:

func generateSecureEnclaveProtectedSecKey(withTag tag: Data) throws -> SecKey {
    var error: Unmanaged<CFError>?
    let accessControl = SecAccessControlCreateWithFlags(
        kCFAllocatorDefault,
        kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
        [.privateKeyUsage],
        &error
    )!

    let attributes = [
        kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
        kSecAttrKeySizeInBits as String: 256,
        kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave,
        kSecPrivateKeyAttrs as String: [
            kSecAttrCanSign as String: true,
            kSecAttrIsPermanent as String: true,
            kSecAttrApplicationTag as String: tag,
            kSecAttrAccessControl as String: accessControl,
        ] as [String: Any],
    ] as [String: Any]

    let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error)!

    return privateKey
}

Then I wanted to use the strongly typed interface of CryptoKit, so I naively tried to get a hold of the existing key as follows (querying for kSecReturnPersistentRef and not kSecReturnRef):

func getSecureEnclaveProtectedCryptoKitKey(fromSecureEnclaveProtectedSecKeyWithTag tag: Data) throws -> SecureEnclave.P256.Signing.PrivateKey {
    let query: [String: Any] = [
        kSecClass as String: kSecClassKey,
        kSecAttrApplicationTag as String: tag,
        kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
        kSecReturnPersistentRef as String: true,
    ]

    var item: CFTypeRef?
    let status = SecItemCopyMatching(query as CFDictionary, &item)

    let keyData = item as! CFData

    return try SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: keyData as Data)
}

But that resulted in:

Error Domain=CryptoTokenKit Code=-3 "corrupted objectID detected" UserInfo={NSLocalizedDescription=corrupted objectID detected}

Since this is a Secure Enclave protected key, it is not possible to use SecKeyCopyExternalRepresentation (or query for kSecReturnData), but perhaps there is another way to convert a SecKey object to a SecureEnclave.P256.Signing.PrivateKey?

The other way around seem to be possible using the answers to this blog post: https://developer.apple.com/forums/thread/728314

Accepted Reply

Is it possible to convert to and from a SecureEnclave.P256.Signing.PrivateKey object and a SecKey object, both representing the same Secure Enclave protected key?

No. Or at least that’s my current understanding. You referenced this thread but I’ve since learnt more on another thread.

Share and Enjoy

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

Replies

I need to correct my original post, as I referred to a forum post (https://developer.apple.com/forums/thread/728314) where one of the answers hinted to that it is possible to convert SecureEnclave.P256.Signing.PrivateKey to a SecKey (representing the exact same key). After reading through the forum post more thoroughly, it actually seems to be the opposite.

Hence I would like to reword my original question:

Is it possible to convert to and from a SecureEnclave.P256.Signing.PrivateKey object and a SecKey object, both representing the same Secure Enclave protected key?

Is it possible to convert to and from a SecureEnclave.P256.Signing.PrivateKey object and a SecKey object, both representing the same Secure Enclave protected key?

No. Or at least that’s my current understanding. You referenced this thread but I’ve since learnt more on another thread.

Share and Enjoy

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