SecItemCopyMatching 始终 returns 'does not appear to be a valid keychain item' 用于存储的 EC 密钥

SecItemCopyMatching always returns 'does not appear to be a valid keychain item' for a stored EC key

我有一个函数可以使用此方法在 iOS 钥匙串中创建一个新密钥:

func initialize(_ keyTag: String) throws -> DeviceBindingParameters {
    let tag = keyTag.data(using: .utf8)!
    let attributes: [String: Any] =
            [kSecAttrKeyType       as String: kSecAttrKeyTypeECSECPrimeRandom,
             kSecAttrKeySizeInBits as String: 256,
             kSecPrivateKeyAttrs   as String: [
                kSecAttrIsPermanent    as String: true,
                kSecAttrLabel          as String: tag,
                kSecAttrApplicationTag as String: tag
             ]
            ]

    ... other stuff
}

然后还有一个检查这个键是否存在的函数:

open func doesKeyExist(_ keyTag: String) -> Bool {
    let tag = keyTag.data(using: .utf8)!
    let query: [String: Any] = [
            kSecClass as String : kSecAttrKeyType,
            kSecAttrLabel as String : tag,
            kSecAttrApplicationTag as String: tag,
            kSecAttrKeyType as String: kSecAttrKeyTypeECSECPrimeRandom,
            kSecReturnRef as String: true
    ]
        
    var item: CFTypeRef?
    let status = SecItemCopyMatching(query as CFDictionary, &item)
    let errorDescription = SecCopyErrorMessageString(status,nil)
    print(errorDescription)
    return status == noErr
}

我只是一个接一个地调用这个方法(为了快速测试,我从 AppDelegate.swift:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    do {
        try crypto.initialize("rohan-key")
        let keyStatus = try crypto.doesKeyExist("rohan-key")
            print("Key status: \(keyStatus)")
    } catch {
        print("errors")
    }

而且我总是得到这个输出:

Optional(The specified item does not appear to be a valid keychain item.)
Key status: false

第一条消息是在 SecItemCopyMatching 的状态下调用 SecCopyErrorMessageString 打印的。此外,我非常确定密钥生成工作正常,因为我使用密钥签署规范消息,通过网络发送它,然后在基于 Java 的后端验证该签名 - 所以这些部分完全没问题.我只是不确定为什么该项目没有保留在密钥库中。

您在 kSecClass as String : kSecAttrKeyType 处犯了一个小错误。 kSecAttrKeyType是表示key类型的key(kSecAttrKeyTypeEC/kSecAttrKeyTypeECSECPrimeRandom/kSecAttrKeyTypeRSA)。所以你应该传递正确的 kSecClass 对你来说应该是 kSecClassKey.

我想指出 SecCopyErrorMessageString 的输出时不时有点糟糕。始终尝试打印 OSStatus 并在 OSStatus. Which in this case would not have given you greatest hits, as it would've returned -50. But the combination of the two identifies them uniquely enough to define it as errSecNoSuchClass found here.

上使用它