When people need to save a password or any other type of sensitive information in an iOS app I see them way too often just storing it in plain text in the NSUserDefaults. This is bad bad bad. Some other times people will try and implement their own encryption or ciphering to hide the real information, but there is no need. From OS X, the iOS implements the keychain. This is Apple’s way of storing things securely for you, and it’s dead easy so there’s no need to store things insecurely.
If you do everything from scratch then it can be a bit of code, but Apple has a keychain wrapper class, download the KeychainItemWrapper.h and KeychainItemWrapper.m from Apple’s site. You will also need to link your project with the Security framework.
This wrapper is similar to an NSDictionary, you set values for keys, however you don’t get to choose the keys and there are a couple of other methods to take into consideration.
The main keys you will need to work with are as follows:
This holds account information, something like an email address or username
This is for the secure data. Passwords, session keys, anything of the sort
When the information above is available. You must specify one of the following: kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAfterFirstUnlock, kSecAttrAccessibleAlways, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly and kSecAttrAccessibleAlwaysThisDeviceOnly.
For most applications kSecAttrAccessibleWhenUnlocked is probably the best option, which means the information is only available when the device is unlocked and will be transferred between backups to other devices
Now you know the basics, it’s time to use this keychain wrapper. The identifier should be unique per keychain item, two different identifiers will represent two different bits of information. The access group can be nil unless you want to share this keychain item among multiple apps.
KeychainItemWrapper* keychain = [[KeychainItemWrapper alloc] initWithIdentifier:@"KeychainTest" accessGroup:nil]; [keychain setObject:kSecAttrAccessibleWhenUnlocked forKey:kSecAttrAccessible]; NSLog(@"%@, %@", [keychain objectForKey:kSecAttrAccount], [keychain objectForKey:kSecValueData]); [keychain setObject:@"firstname.lastname@example.org" forKey:kSecAttrAccount]; [keychain setObject:@"MySuperSecretPassword" forKey:kSecValueData]; [keychain release]; keychain = nil;
The first time you run this there will be no entries for the account and data fields, run it again and you will get the information from the previous time. When the user logs out or you need to clear the data, call [keychain resetKeychainItem];