I would like to know if there is a way to reset my app's Keychain. I am wondering whether anything like [NSUserDefaults resetStandardUserDefaults]
exists for keychain. Keychain is not reset even after the app is deleted. So far the only way I know is to reset them one by one from the app.
Asked
Active
Viewed 2.3k times
25

Josh Correia
- 3,807
- 3
- 33
- 50

Jose Cherian
- 7,207
- 3
- 36
- 39
-
@serge-k , that question was asked in 2012 while this one was in 2011. – Jose Cherian Mar 02 '16 at 20:24
-
True, just figured the other answer found here http://stackoverflow.com/questions/14086085/how-to-delete-all-keychain-items-accessible-to-an-app is a more up to date solution. I can just leave it as a link, I removed duplicate flag. – serge-k Mar 02 '16 at 21:35
4 Answers
64
As all of the answers so far rely on you knowing the identifiers you want to delete, I would like to submit the following solution that deletes ALL existing keys for the app (iOS only)
Objective-C:
-(void)resetKeychain {
[self deleteAllKeysForSecClass:kSecClassGenericPassword];
[self deleteAllKeysForSecClass:kSecClassInternetPassword];
[self deleteAllKeysForSecClass:kSecClassCertificate];
[self deleteAllKeysForSecClass:kSecClassKey];
[self deleteAllKeysForSecClass:kSecClassIdentity];
}
-(void)deleteAllKeysForSecClass:(CFTypeRef)secClass {
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
[dict setObject:(__bridge id)secClass forKey:(__bridge id)kSecClass];
OSStatus result = SecItemDelete((__bridge CFDictionaryRef) dict);
NSAssert(result == noErr || result == errSecItemNotFound, @"Error deleting keychain data (%ld)", result);
}
Swift 2.2:
func resetKeychain() {
self.deleteAllKeysForSecClass(kSecClassGenericPassword)
self.deleteAllKeysForSecClass(kSecClassInternetPassword)
self.deleteAllKeysForSecClass(kSecClassCertificate)
self.deleteAllKeysForSecClass(kSecClassKey)
self.deleteAllKeysForSecClass(kSecClassIdentity)
}
func deleteAllKeysForSecClass(secClass: CFTypeRef) {
let dict: [NSString : AnyObject] = [kSecClass : secClass]
let result = SecItemDelete(dict)
assert(result == noErr || result == errSecItemNotFound, "Error deleting keychain data (\(result))")
}
Swift 3:
func resetKeychain() {
deleteAllKeysForSecClass(kSecClassGenericPassword)
deleteAllKeysForSecClass(kSecClassInternetPassword)
deleteAllKeysForSecClass(kSecClassCertificate)
deleteAllKeysForSecClass(kSecClassKey)
deleteAllKeysForSecClass(kSecClassIdentity)
}
func deleteAllKeysForSecClass(_ secClass: CFTypeRef) {
let dict: [NSString : Any] = [kSecClass : secClass]
let result = SecItemDelete(dict as CFDictionary)
assert(result == noErr || result == errSecItemNotFound, "Error deleting keychain data (\(result))")
}

Josh Correia
- 3,807
- 3
- 33
- 50

Vegard
- 4,352
- 1
- 27
- 25
-
4is there a way to delete all the keychains manually using the phone itself? something like the instructions [here](http://www.imore.com/how-access-and-view-your-icloud-keychain-passwords-ios-7) – abbood Jul 26 '14 at 05:55
-
2@abbood programmatically that should be impossible. Why? Because your app is sandboxed and you would never be able to delete all keychain items **from other apps**. The only I'm *guessing* possible scenario would be to use the simulator itself `iOS Simulator -> Reset Content and Settings` – mfaani Oct 18 '16 at 15:52
11
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"nameOfYourKeychain" accessGroup:nil];
[keychainItem resetKeychainItem];
Much simpler :)
Edit: In response to a question asked below - what is KeychainItemWrapper?
It's a class written by Apple that you can download here: http://developer.apple.com/library/ios/#samplecode/GenericKeychain/Listings/Classes_KeychainItemWrapper_m.html
Add it to your project and then import it where you would like to use it. Then use the code snippet I provided above.

jcrowson
- 4,290
- 12
- 54
- 77
-
2
-
1Thanks, but if I need to have several key-value pairs, and I cannot use a dictionary for all my stuff and store it against standard key like `kSecValueData` because the value need to be a string, then I need to create as many `KeychainItemWrapper` as the number of my key-value pairs? – hzxu Mar 11 '13 at 22:09
-
@hzxu exactly, [kechainItem resetKeychainItem] should only be used to reset the default attributes of the keychain, namely kSecAttrAccount, kSecAttrLabel, kSecAttrDescription and as you mentioned kSecValueData. Also keep in mind, that this is only for sample code provided by Apple which works with the kSecClassGenericPassword. – serge-k Mar 02 '16 at 17:00
-
1
2
Block-based version of Vegard’s solution:
void (^deleteAllKeysForSecClass)(CFTypeRef) = ^(CFTypeRef secClass) {
id dict = @{(__bridge id)kSecClass: (__bridge id)secClass};
OSStatus result = SecItemDelete((__bridge CFDictionaryRef) dict);
NSAssert(result == noErr || result == errSecItemNotFound, @"Error deleting keychain data (%d)", (int)result);
};
deleteAllKeysForSecClass(kSecClassGenericPassword);
deleteAllKeysForSecClass(kSecClassInternetPassword);
deleteAllKeysForSecClass(kSecClassCertificate);
deleteAllKeysForSecClass(kSecClassKey);
deleteAllKeysForSecClass(kSecClassIdentity);
For those of us who like to just drop code in without having to have helper methods.

Josh Correia
- 3,807
- 3
- 33
- 50

mxcl
- 26,392
- 12
- 99
- 98
-
Thanks for this. It's also the simplest and most expressive implementation. – Joey Carson Jun 30 '16 at 15:12
-5
- (void)resetKeychainItem
{
OSStatus junk = noErr;
if (!keychainItemData) {
self.keychainItemData = [[NSMutableDictionary alloc] init];
} else if (keychainItemData){
NSMutableDictionary *tempDictionary = [self dictionaryToSecItemFormat:keychainItemData];
junk = SecItemDelete((CFDictionaryRef)tempDictionary);
if ( junk != noErr ) {
UIAlertView *dialog = [[UIAlertView alloc] initWithTitle:@"Keychain Error" message:[NSString stringWithFormat:@"A problem with updating the secure Keychain items with this information (likely, this email address information is duplicated in another Player). Error code: %d %@", junk, [self resultText:-junk]] delegate:self cancelButtonTitle:NSLocalizedStringFromTable(@"Ok", @"Localizable", @"display text") otherButtonTitles:nil];
[dialog show];
[dialog release];
//NSAssert( junk == noErr || junk == errSecItemNotFound, @"Problem deleting current dictionary." );
return;
}
}
// Default attributes for keychain item.
[keychainItemData setObject:@"" forKey:(id)kSecAttrAccount];
[keychainItemData setObject:@"" forKey:(id)kSecValueData];
[keychainItemData setObject:@"" forKey:(id)kSecAttrLabel];
[keychainItemData setObject:@"" forKey:(id)kSecAttrDescription];
[keychainItemData setObject:@"" forKey:(id)kSecAttrComment];
// Default data for keychain item.
[keychainItemData setObject:@"" forKey:(id)kSecAttrModificationDate];
[keychainItemData setObject:@"" forKey:(id)kSecAttrService];
}

JimP
- 87
- 5
-
Can you add some comments to help users understand what your code is doing – Matt Wilko Aug 22 '11 at 13:52
-
@JimP, could you give a bit of explanation. you still need to provide all the keys to reset right? I have a lot of secure info and I want to reset all of them there is a need. – Jose Cherian Aug 23 '11 at 03:43
-
Code snippet comes from Apple's sample code. https://developer.apple.com/library/ios/samplecode/GenericKeychain/Listings/Classes_KeychainItemWrapper_m.html – Tony Oct 19 '13 at 19:30