Search code examples
iosobjective-ckeychainkeychainitemwrapper

How to store a password in iOS 7 using ARC


I'm working on an app for iOS 7 and am using ARC. I am using a web service so users have to log into the web service with a username and password. I'm know it's not good to just store the username and password as is so I would like to use keychain to store the username and password.

After doing some research it seems like people suggest using KeychainItemWrapper however that is not compatible with ARC. How can I store passwords using keychain in iOS 7 using ARC? Any help and guidelines would be greatly appreciated.


Solution

  • I use the following:

    + (void)keyChainSaveKey:(NSString *)key data:(id)data
    {
        NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];
        SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
        [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge id)kSecValueData];
        SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
    }
    
    + (id)keyChainLoadKey:(NSString *)key
    {
        id ret = nil;
        NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];
        [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
        [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
        CFDataRef keyData = NULL;
        if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
            @try {
                ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
            }
            @catch (NSException *e) {
                //NS Log(@"Unarchive of %@ failed: %@", service, e);
            }
            @finally {}
        }
        if (keyData) CFRelease(keyData);
        return ret;
    }
    
    + (void)keyChainDeleteKey:(NSString *)service
    {
        NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
        SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
    }
    
    //helper
    + (NSMutableDictionary *)getKeychainQuery:(NSString *)key
    {
        return [NSMutableDictionary dictionaryWithObjectsAndKeys:
                (__bridge id)kSecClassGenericPassword, (__bridge id)kSecClass,
                key, (__bridge id)kSecAttrService,
                key, (__bridge id)kSecAttrAccount,
                (__bridge id)kSecAttrAccessibleAfterFirstUnlock, (__bridge id)kSecAttrAccessible,
                nil];
    }
    

    You might need to

    #import <CommonCrypto/CommonCryptor.h>
    

    I don't remember where I found this code... so I can't give credit :(