Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you reset an iPhone App's Keychain?

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.

like image 266
Jose Cherian Avatar asked Aug 22 '11 03:08

Jose Cherian


People also ask

How do you clear keychain for an app iOS?

If you have a Mac, then you can use the macOS /Applications/Utilities/Keychain Access. app and select iCloud on the left to see the content. Search for the app name or company name. Once you have found the item and are absolutely sure it's the right one, simply delete it.

What is an application password on keychain?

App-specific passwords are passwords for your Apple ID that let you sign in to your account and securely access the information you store in iCloud from a third-party app. For example, use app-specific passwords with mail, contacts, and calendar services not provided by Apple.


3 Answers

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))")
}
like image 123
Vegard Avatar answered Sep 25 '22 17:09

Vegard


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.

like image 43
jcrowson Avatar answered Sep 21 '22 17:09

jcrowson


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.

like image 27
mxcl Avatar answered Sep 22 '22 17:09

mxcl