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.
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.
- (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];
}
精彩评论