For some reason I can't get this simple keychain code to work.
//Let's create an empty mutable dictionary:
NSMutableDictionary *keychainItem = [NSMutableDictionary dictionary];
NSString *username = self.nwUsernameTxtFld.text;
NSString *password = self.passwordTxtFld.text;
//Populate it with the data and the attributes we want to use.
keychainItem[(__bridge id)kSecClass] = (__bridge id)kSecClassInternetPassword; // We specify what kind of keychain item this is.
keychainItem[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleWhenUnlocked; // This item can only be accessed when the user unlocks the device.
keychainItem[(__bridge id)kSecAttrServer] = @"http://www.myawesomeservice.com";
keychainItem[(__bridge id)kSecAttrAccount] = username; //Our username.
if(SecItemCopyMatching((__bridge CFDictionaryRef)keychainItem, NULL) == noErr)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"The Item Already Exists", nil)
message:NSLocalizedString(@"Please update it instead.", )
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil];
[alert show];
}else
{
NSLog(@"can add new item.");
keychainItem[(__bridge id)kSecValueData] = password; //Our password
OSStatus sts = SecItemAdd((__bridge CFDictionaryRef)keychainItem, NULL);
NSLog(@"%d", (int)sts);
}
I have checked Apple's documentation on the matter and according to it:
One or more parameters passed to the function were not valid.
Yet, the SecAddItem
function takes two paramters:
OSStatus SecItemAdd (
CFDictionaryRef attributes,
CFTypeRef *result
);
I am passing NULL to result. This is acceptable according to Apple's documentation:
result On return, a reference to the newly added items. The exact type of the result is based on the values supplied in attributes, as discussed below. Pass NULL if this result is not required.
So I Don't really know what I'm doing wrong here. I'm passing it a dictionary and a NULL value. The function expects both and I'm giving it both. Can someone please enlighten me as to what's wrong?
For reference, the documentation is here.
You are inserting an incorrect data type into the dictionary for the key kSecValueData
. As indicated in the documentation at the bottom of your question, it needs to be CFDataRef
(or bridged NSData
) but you are inserting an NSString
instead. It is a trivial matter to convert NSString
to NSData
and once you do so you will stop having this error.