开发者

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];


}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜