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.
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.
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.
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))")
}
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With