如何从钥匙串中获取数字身份?

How to obtain a digital identity from the keychain?

我正在学习 Apple 的教程:https://developer.apple.com/documentation/security/certificate_key_and_trust_services/certificates/storing_a_certificate_in_the_keychain

https://developer.apple.com/documentation/security/certificate_key_and_trust_services/identities/storing_an_identity_in_the_keychain

关于如何从钥匙串中存储和检索身份。

存储身份似乎工作正常,返回 errSecSuccess。但是,在尝试获取任何身份时,我会返回 errSecItemNotFound(或 -25300)。

即使转储钥匙串也无法正常工作;添加身份成功后,SecItemCopyMatching还是returnserrSecItemNotFound

请参阅以下与文档中提供的摘录非常匹配的代码:

// Store the digital identity in the keychain:
let addQuery: [String : Any] = [kSecClass as String: kSecClassIdentity,
                                kSecValueRef as String: identity,
                                kSecAttrLabel as String: "myid"]

guard SecItemAdd(addQuery as CFDictionary, nil) == errSecSuccess else {
    print("Could not store identity in keychain")
    return false
}

// Obtain the digital identity from the keychain:
let getQuery: [String : Any] = [kSecClass as String: kSecClassIdentity,
                                kSecAttrLabel as String: "myid",
                                kSecReturnRef as String: kCFBooleanTrue!]
var item: CFTypeRef?
let status = SecItemCopyMatching(getQuery as CFDictionary, &item)
guard status == errSecSuccess else {
    print("Could not find identity in keychain, OSerror: \(status)") // <---- -25300
    return false
}

let localIdentity = item as! SecIdentity

// [...]

为了完成,这就是我 "dump" 钥匙串(至少是身份)的方式:

let getQuery: [String : Any] = [kSecClass as String : secClass,
                                kSecReturnData as String  : kCFBooleanTrue!,
                                kSecReturnAttributes as String : kCFBooleanTrue!,
                                kSecReturnRef as String : kCFBooleanTrue!,
                                kSecMatchLimit as String : kSecMatchLimitAll]
var items: CFTypeRef?
let status = SecItemCopyMatching(getQuery as CFDictionary, &items) // <--- again, status = -25300

缺少什么?

我多次浏览文档。将物品存储在钥匙串中需要一些时间吗?如果有,苹果提供的例子有没有提到?

为什么我在存储项目时得到一个 errSecSuccess 但它不会让我立即阅读该项目?

我也在真实设备上进行测试。

我终于自己找到了答案。

Using labels on an identity is tricky because identities are not stored in the keychain as an atomic item but are store as a separate private key and certificate, and those items use labels in different ways. 

https://forums.developer.apple.com/thread/98029

即:

  1. 将身份添加到钥匙串时将 kSecReturnPersistentRef 传递给 SecItemAdd
  2. 在任何地方保存持久引用
  3. 稍后,当您需要返回身份时,使用该持久引用调用 SecItemCopyMatching

这是有道理的,我终于能够通过这种方式解决我的问题。