macOS Keychain : SecItemDelete wiped out all identities

I just wiped out all the identities in my Keychain while trying to erase just one from the Keychain.


I have boilerplate code along the lines of :


+(void)eraseCertificatesWithLabel:(NSString *)label
{
NSDictionary *eraseQuery = @{
  (__bridge id)kSecClass : (__bridge id)kSecClassCertificate,
  (__bridge id)kSecAttrLabel : label,
  (__bridge id)kSecMatchLimit : (__bridge id)kSecMatchLimitAll,
  };

OSStatus delErr = SecItemDelete((__bridge CFDictionaryRef)eraseQuery);
}


same for

+(void)erasePrivateKeysWithLabel:(NSString *)label;


You get the picture.


Now here is what happens.

If I erase the Private Key first, then I cannot erase the certificate. When I call eraseCertificatesWithLabel, OSStatus returns 0 but I can still see the certificate in the Keychain. The funny thing is that when I inspect the Keychain with the Keychain Access App, the certificate is present in the 'Certificates' section, but not in 'my Certificates'. Then, if I remove it manually from the Keychain, I see an alert message that says that I am trying to remove a non-existent item. But, after getting that message the certificate disappears from the Keychain.


I thought 'OK, looks like a broke an identity pair. Instead of erasing the certificates and the private keys independently, I should erase the identity in a single pass'.


So I wrote

+(void)eraseIdentitiesWithLabel:(NSString *)label;


Now this is where the big wipe happened.

It erased all the identities that were in the Keychain. For instance I accidentally erased my XCode signing identities by calling this function, as well as a bunch of other stuff which was in my Keychain. Strangely, my function eraseIdentitiesWithLabel returned OSStatus of -61 (write permission). So it looks that not only my label was ignored, but in addition

SecItemDelete
knew that it was not authorized to delete these items. Yet it still deleted them.


Here is what I'd like to do. Very simple :

1. Use the regular, standard keychain to put items (

SecKeyRef
,
SecCertificateRef
,
SecIdentityRef
) that belong to my app

2. Make sure I don't mess with stuff that doesn't belong to my app (and respectively, make sure other apps won't mess with my stuff)

3. Be able to implement the functions on both OSX and iOS (Just to be clear. I am comfortable with the fact that the code has to be customized for each platform. I can maintain two different code bases, that's fine for me)


The way I've tried to implement it is by using

kSecAttrLabel
as a way to tag my items. Now this feels like a big mistake.

I am opening this post because I just want to know what is the best way to use the keychain.



Many thanks

Accepted Reply

I too have accidentally wiped all the identities from my keychain )-: In my case I was working in a private keychain (because I wanted to reset the keychain as part of my unit tests) and I discovered the hard way that the Mac’s

SecItemDelete
ignores the
kSecUseKeychain
parameter (r. 21063746).

Here is what I'd like to do.

If you have an identity (

SecIdentityRef
) you should be able to get the key and certificate from that (
SecIdentityCopyPrivateKey
,
SecIdentityCopyCertificate
) and delete those based on their ref (
kSecValueRef
) rather than their attributes. In my experience that overall strategy works reasonably well on both platforms.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

I too have accidentally wiped all the identities from my keychain )-: In my case I was working in a private keychain (because I wanted to reset the keychain as part of my unit tests) and I discovered the hard way that the Mac’s

SecItemDelete
ignores the
kSecUseKeychain
parameter (r. 21063746).

Here is what I'd like to do.

If you have an identity (

SecIdentityRef
) you should be able to get the key and certificate from that (
SecIdentityCopyPrivateKey
,
SecIdentityCopyCertificate
) and delete those based on their ref (
kSecValueRef
) rather than their attributes. In my experience that overall strategy works reasonably well on both platforms.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

kSecValueRef
looks like the right strategy indeed. I'll give it a shot. Thanks