IOS:无法从 CryptoKit SecureEnclave 私钥创建 SecKey 表示(OSStatus 错误 -50 - 从数据创建 EC 私钥失败)

IOS: Unable to create SecKey representation from CryptoKit SecureEnclave Private Key (OSStatus error -50 - EC private key creation from data failed))

我正在尝试使用 CryptoKitSecureEnclave 中创建一个 Private/Public 密钥对,然后将对私钥的引用保存在 KeyChain 中以供进一步使用用法。密钥生成完全正常:

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]

但是当我尝试将刚刚创建的密钥转换为 SecKey 以便稍后将其存储在钥匙串中时:

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

失败并出现错误:

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

另一方面,当我删除 SecureEnclave 元素并使用 x963Representation 时,我能够将私钥转换为 SecKey 对象:

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

关于为什么会发生这种情况或者我该如何解决这个问题有什么想法吗?

并非所有密钥都可以(直接)存储到钥匙串中as described in the documentation。要解决此问题,您可以将原始 Data 作为通用密码存储在钥匙串中。 SecureEnclave 键有点不幸。

此外,Secure Enclave 私钥的 .dataRepresentation 不是安全框架所理解的。 Secure Enclave 密钥不打算被提取(据我所知根本无法提取)。您提取的 blob 是一个容器,同一个 enclave 可以使用它来重建私钥。在另一个 iPhone 上使用相同的数据将不会重新创建密钥。

我不确定将此 blob 作为文件存储在设备上是否存在安全风险。所以我建议你看看前面提到的文档并使用 GenericPasswordConvertible 示例。