首页 > 解决方案 > IOS:无法从 CryptoKit SecureEnclave 私钥创建 SecKey 表示(OSStatus 错误 -50 - 从数据创建 EC 私钥失败))

问题描述

SecureEnclave我正在尝试在with中创建一个私钥/公钥对CryptoKit,然后保存对私钥的引用以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()
}

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

标签: iosswiftkeychainpublic-key-encryptionapple-cryptokit

解决方案


如文档中所述,并非所有密钥都可以(直接)存储到钥匙串中。要解决此问题,您可以将原始Data密码作为通用密码存储在钥匙串中。SecureEnclave钥匙有点可惜。

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

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


推荐阅读