将保存证书颁发给 iOS Keychain -25300(未找到)如果删除,但 -25299(重复项)如果添加

Issue Saving Certificate to iOS Keychain -25300 (not found) if deleting, but -25299 (duplicate item) if adding

我在使用 Apple 钥匙串时遇到了一个有趣的问题,想知道我做错了什么。

    func saveCert(accessGroup: String? = nil, certData: Data, label: String? = nil) -> Error? {
        var query = createKeychainAddQueryDict()
        if let accessGroup = accessGroup {
            query[String(kSecAttrAccessGroup)] = accessGroup
        }

        query[String(kSecValueData)] = certData
        query[String(kSecClass)] = kSecClassCertificate

        if let label = label {
            query[String(kSecAttrLabel)] = label
        }

        var status = SecItemDelete(query as CFDictionary)
        if status != noErr {
            print("Error deleting cer from keychain. Error: \(status)")
        }

        let resultCode = SecItemAdd(query as CFDictionary, nil)
        return getErrorFromKeychainCode(code: resultCode)
    }

我正在保存自签名证书,但我已验证我尝试存储的每件商品的序列号都不同。

当我尝试删除证书时出现 -25300 错误(找不到项目),但当我尝试保存到钥匙串时出现 -25299 错误(重复项目已存在)。

我很困惑为什么或如何,从该位置加载或删除密钥都失败了,保存就是声明该位置已被占用。

有什么见解吗?我已经尝试过对一些我以前从未使用过的随机标签进行硬编码,但它们也会出现重复输入错误。

我找到了两个解决方案:

  1. 稍后请求特定键的值。使用异步延迟。 Keychain 有时不提供 -25300 的结果。钥匙串也是一个 SQLite 数据库。看来数据库当前正忙。所以,稍后请求数据。
  2. 您已经在此密钥中写入了一些内容,但是您使用了另一个保护级别。为避免这种情况,请使用名称中包含保护级别的密钥。例如,someKey 变成 someKey-afterFirstUnlock

我尝试了很多东西,其中 none 成功了。我最终发现 kSecCertificate class 使用发行者和序列号属性来计算其 uniqueId。

因为我使用的是自签名证书,所以 SecCertificateCreateWithData 操作失败,结果为 nil。我相信这会导致我所有的证书都评估为相同的空 - 空 id。我尝试将相同的数据存储在 kSecGenericPassword 中,并设置一个不同的帐户属性,然后问题就消失了。