如何使用SecIdentityRef或持久引用从钥匙串中删除身份信息?

4

Keychain Services的文档非常不完整,每当我尝试使用SecItem*()函数时,总是会收到没有帮助的错误信息。目前,我正在尝试删除我之前添加到钥匙串中的一个身份标识:

// Identity ref is a persistent reference to the identity I want to delete.
NSData *identityRef = ...
NSDictionary *query = @{ (id)kSecClass: (id)kSecClassIdentity,
                         (id)kSecValuePersistentRef: identityRef };
OSStatus status = SecItemDelete((CFDictionaryRef)query);
// Fails with errSecParam (-50) under iOS 6
// Fails with errSecNotAvailable (-25291) under iOS 7

然而,据我所知,各种安全项目类别所需的(和建议的)参数似乎没有任何文件记录。为了成功地使用钥匙串中的身份标识,我应该指定什么?

编辑

我也尝试使用文档中记录的 kSecMatchItemList

NSDictionary *query = @{ (id)kSecClass: (id)kSecClassIdentity,
                         (id)kSecMatchItemList: @[identityRef] };
OSStatus status = SecItemDelete((CFDictionaryRef)query);
// Fails with errSecParam (-50)

我也尝试了从这个SO问题中提供的建议主键:

NSDictionary *attrs = nil;
NSDictionary *attrsQuery = @{ (id)kSecClass: (id)kSecClassIdentity,
                              (id)kSecValuePersistentRef: identityRef };
SecItemCopyMatching(attrsQuery, (CFTypeRef *)&attrs);
NSDictionary *query = @{ (id)kSecClass: (id)kSecClassIdentity,
                         (id)kSecAttrCertificateType: attrs[(id)kSecAttrCertificateType],
                         (id)kSecAttrIssuer: attrs[(id)kSecAttrIssuer],
                         (id)kSecAttrSerialNumber: attrs[(id)kSecAttrSerialNumber],
                         (id)kSecAttrApplicationLabel: attrs[(id)kSecAttrApplicationLabel],
                         (id)kSecAttrApplicationTag: attrs[(id)kSecAttrApplicationTag],
                         (id)kSecAttrKeyType: attrs[(id)kSecAttrKeyType],
                         (id)kSecAttrKeySizeInBits: attrs[(id)kSecAttrKeySizeInBits],
                         (id)kSecAttrEffectiveKeySize: attrs[(id)kSecAttrEffectiveKeySize] };
OSStatus status = SecItemDelete(query);
// Still fails with errSecParam (-50)
2个回答

4

看起来我对要删除的项目进行了过度指定。如果在从钥匙串中删除身份验证信息时查询中包含 kSecClass 键,则会使密钥链服务困惑。以下代码可以正常工作:

NSData *identityRef = ...
NSDictionary *query = @{ (id)kSecValuePersistentRef: identityRef };
OSStatus status = SecItemDelete((CFDictionaryRef)query); // Success!

0

Keychain可以被视为一个带有许多表(kSecClass)的数据库。

由于您正在使用kSecClassIdentity,因此这个“表”有两个主键,分别是kSecClassKeykSecClassCertificate

在进行条目操作时,您应始终指定这些值。在您的情况下,查询字典缺少这些值。

您可以查看此SO帖子以获取有关keychain类的主键的更多信息

什么使keychain项目在iOS中独特?


我该如何指定证书和密钥?我不能在查询中为 kSecValueRef 指定多个值。我已尝试按链接帖子所述指定 kSecAttrCertificateTypekSecAttrIssuerkSecAttrSerialNumberkSecAttrApplicationLabelkSecAttrApplicationTagkSecAttrKeyTypekSecAttrKeySizeInBitskSecAttrEffectiveKeySize,但仍然收到 errSecParam 错误。 - Greg
如果我是你,而且你不介意失去数据的话,我会清除整个密钥链中与类身份有关的内容。顺便问一下,你需要保存什么?你确定 kSecClassIdentity 是适合你的吗? - streem
是的,我正在存储多个TLS客户端证书和密钥,以便用户可以使用不同的身份连接到不同的服务器。为了不让钥匙串充满垃圾,我正在尝试让用户删除未使用的身份。 - Greg
好的,我不熟悉那个类,但我猜它与kSecClassGenericPassword并没有太大的区别。你的查询应该在SecItemCopyMatching和SecItemDelete中包含3个属性(精确地),它们是主键(kSecClassKey和kSecClassCertificate)和类kSecClassIdentity。 - streem
话虽如此,你能清除你的钥匙串吗?如果它已经损坏,那么你就没什么办法了。 - streem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接