How do I delete an identity from the keychain using a SecIdentityRef or persistent reference?

ios, keychain

Solution

It appears I was overspecifying the item to delete. If you include the `kSecClass` key in the query when deleting an identity from the keychain, Keychain Services gets confused. This code works:

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

Problem

The documentation for Keychain Services is horribly incomplete and I keep getting unhelpful errors when I try to use the SecItem*() functions. Currently I'm trying to delete an identity I've previously added to the keychain: ``` // 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 ``` However, the required (and recommended) parameters for each of the various security item classes are not documented anywhere as far as I can tell. What should I be specifying in order to successfully work with identities in the keychain? EDIT I have also tried using `kSecMatchItemList` as documented: ``` NSDictionary *query = @{ (id)kSecClass: (id)kSecClassIdentity, (id)kSecMatchItemList: @[identityRef] }; OSStatus status = SecItemDelete((CFDictionaryRef)query); // Fails with errSecParam (-50) ``` I have also tried specifying the suggested primary keys from this SO question: ``` 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) ```

Original source

Related problems