How to delete all keychain items accessible to an app?
Asked Answered
H

8

56

I have stray keychain items on iOS (probably written by old version of app) that I need to delete. Is there an easy way to achieve this?

Hanrahan answered 29/12, 2012 at 21:27 Comment(2)
see #10967469 for getting all items you can access, then remove each one ..Malemute
I'm looking for a method to delete keychain items for a specific App on my iPhone. I really need it since these Apps are not developed by me.Banyan
M
93

Do it for all classes

Objective-C:

NSArray *secItemClasses = @[(__bridge id)kSecClassGenericPassword,
                       (__bridge id)kSecClassInternetPassword,
                       (__bridge id)kSecClassCertificate,
                       (__bridge id)kSecClassKey,
                       (__bridge id)kSecClassIdentity];
for (id secItemClass in secItemClasses) {
    NSDictionary *spec = @{(__bridge id)kSecClass: secItemClass};
    SecItemDelete((__bridge CFDictionaryRef)spec);
}

Swift:

      [kSecClassGenericPassword, kSecClassInternetPassword, kSecClassCertificate, kSecClassKey, kSecClassIdentity].forEach {
        let status = SecItemDelete([
          kSecClass: $0,
          kSecAttrSynchronizable: kSecAttrSynchronizableAny
        ] as CFDictionary)
        if status != errSecSuccess && status != errSecItemNotFound {
            //Error while removing class $0
        }
      }
Malemute answered 29/12, 2012 at 22:2 Comment(6)
I use a literal for NSDictionary so its xcode4.5+ but if someneone needs older gcc/llvm support use dictionaryWithObject:forKey:Malemute
That's not a dictionary literal, it should be NSDictionary *spec = @{(__bridge id)kSecClass: secItemClass};Amazonite
Typo is not fixed. the cast needs to be moved before kSecClass, as kevboh specified.Pee
latest down voter would you please leave a comment so I can fix it if neededMalemute
I think kSecAttrAccount is missingMyrica
I'm login using open office 365, but my oauth2 lib not logout Keychain. Any have idea please comment here.Humfrey
U
15

Xamarin iOS version (MonoTouch) of accepted answer on How to delete all keychain items accessible to an app is below:

foreach (var recordKind in new []{
                SecKind.GenericPassword,
                SecKind.Certificate,
                SecKind.Identity,
                SecKind.InternetPassword,
                SecKind.Key,
            })
    {
          SecRecord query = new SecRecord(recordKind);
          SecKeyChain.Remove(query);
    }

If you want to make sure you indeed delete the records, you may during development check number of items in KeyChain of specific kind before and after with this code:

SecStatusCode scc;
var records = SecKeyChain.QueryAsRecord(new SecRecord(SecKind.GenericPassword), 1000, out scc);
Unbeknown answered 14/8, 2014 at 5:40 Comment(0)
F
15

I rewrote Daij-Djan's answer in Swift:

let secItemClasses = [kSecClassGenericPassword,
    kSecClassInternetPassword,
    kSecClassCertificate,
    kSecClassKey,
    kSecClassIdentity]
for secItemClass in secItemClasses {
    let dictionary = [kSecClass as String:secItemClass]
    SecItemDelete(dictionary as CFDictionary)
}
Fathometer answered 7/11, 2015 at 4:43 Comment(3)
This code caused crashes for me. The issue occurred with the CFHash to Int conversion in the hashValue variable (at least on 32 bit platforms). CFHash returns a UINT which may overflow when converted to an Int in swift. I suggest changing that line to public var hashValue: Int {return Int(bitPattern:CFHash(self))} to ensure it will not overflow.Malia
CFString is toll free bridged to NSString which is bridged to swift strings so you can just cast them, i.e. let dictionary = [kSecClass as String : secItemClass as String]Mousterian
Swift 3 compiler will complain unless you write: "SecItemDelete(dictionary as CFDictionary)"Telegonus
P
12

Swift version

import Foundation
import Security


public class Keychain: NSObject {
  public class func logout()  {
    let secItemClasses =  [
      kSecClassGenericPassword,
      kSecClassInternetPassword,
      kSecClassCertificate,
      kSecClassKey,
      kSecClassIdentity,
    ]
    for itemClass in secItemClasses {
      let spec: NSDictionary = [kSecClass: itemClass]
      SecItemDelete(spec)
    }
  }
}

usage:

Keychain.logout()
Passenger answered 31/12, 2018 at 1:14 Comment(2)
I like this solution because It has an API.Gipsy
Thanks @AlanAndradePassenger
H
7

Thanks to Daij-Djan I got to this solution:

for (id secclass in @[
     (__bridge id)kSecClassGenericPassword,
     (__bridge id)kSecClassInternetPassword,
     (__bridge id)kSecClassCertificate,
     (__bridge id)kSecClassKey,
     (__bridge id)kSecClassIdentity]) {
    NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                  secclass, (__bridge id)kSecClass,
                                  nil];

    SecItemDelete((__bridge CFDictionaryRef)query);        
}
Hanrahan answered 29/12, 2012 at 22:2 Comment(2)
I got the same now :D heheMalemute
nice to see that for once the OP works with you on an answer :)Malemute
A
5

Unfortunately all answers of this question seem to be outdated (since iOS 7.0+) as they do not delete keychain entries that have the kSecAttrSynchronizable flag set (allow synchronization to other devices through iCloud).

To delete such entries it is crucible to add an entry to the delete query specifying kSecAttrSynchronizable: kSecAttrSynchronizableAny:

Swift version:

let secItemClasses = [kSecClassGenericPassword,
    kSecClassInternetPassword,
    kSecClassCertificate,
    kSecClassKey,
    kSecClassIdentity]
for secItemClass in secItemClasses {
    let query: NSDictionary = [
        kSecClass as String: secItemClass,
        kSecAttrSynchronizable as String: kSecAttrSynchronizableAny
    ]
    SecItemDelete(query)
}
Annecy answered 30/3, 2021 at 13:3 Comment(0)
A
1

You could take a look at the KeyChain Access application found in the Utilities folder. If you launch the application and click on "All Items," it should display all the items you have created with this specific computer. The developer ones usually start with com.

Andri answered 29/12, 2012 at 21:35 Comment(3)
For Mac your answer is perfect but on iOS the Keychain Access app doesn't exist. Thanks anyway!Hanrahan
It's a good idea, however, it seems that the keychain item for a specific App in the iPhone is not accessible on my Mac, although I did make my keychain stored on the iCloud.Banyan
I'm looking for the method to delete keychain for a specific App manually.Banyan
T
1

Be cautious on using kSecClassCertificate to clear out all when you're unit testing using a Mac as a target as this will clear your development certificate. You can simply revoke the existing but in a CI/CD pipeline this won't work.

Twenty answered 16/3, 2022 at 11:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.