I have the following methods in which I create a keychain item and add it to the keychain using SecItemAdd()
. When I attempt to retrieve the password, I am unable to see it in my console. I am running on a device, not simulator.
- (NSMutableDictionary *)createKeychainDictionaryWithIdentifier:(NSString *)identifier username:(NSString *)username password:(NSString *)password{
NSMutableDictionary *dict = [@{} mutableCopy];
[dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
NSData *identifierData = [identifier dataUsingEncoding:NSUTF8StringEncoding];
NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
[dict setObject:(__bridge id)kSecAttrAccessibleWhenUnlocked forKey:(__bridge id)kSecAttrAccessible];
[dict setObject:identifierData forKey:(__bridge id)kSecAttrGeneric];
[dict setObject:username forKey:(__bridge id)kSecAttrAccount];
[dict setObject:passwordData forKey:(__bridge id)kSecValueData];
[dict setObject:service forKey:(__bridge id)kSecAttrService];
return dict;
}
- (BOOL)addClientWithKeyChainIdentifier:(NSString *)identifier username:(NSString *)username password:(NSString *)password{
NSMutableDictionary *client = [self createKeychainDictionaryWithIdentifier:identifier username:username password:password];
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)client, NULL);
if(status != errSecSuccess)
return NO;
DLog(@"status: %i", (int)status);
//Add identifier to clients array
[_clients addObject:identifier];
return YES;
}
- (NSDictionary *)searchForItemWithIdentifier:(NSString *)identifier{
NSMutableDictionary *searchDict = [@{} mutableCopy];
NSData *identifierData = [identifier dataUsingEncoding:NSUTF8StringEncoding];
//Define search dictionary
[searchDict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
[searchDict setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
[searchDict setObject:identifierData forKey:(__bridge id)kSecAttrGeneric];
[searchDict setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes];
CFDictionaryRef dict = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)searchDict, (CFTypeRef *) &dict);
if(status != errSecSuccess)
return nil;
NSDictionary *result = (__bridge NSDictionary *)dict;
return result;
}
Here is the code where I test the above methods:
[keychainManager addClientWithKeyChainIdentifier:@"Nikita" username:@"Nikita" password:@"Volkov"]
NSDictionary *dict = [keychainManager searchForItemWithIdentifier:@"Nikita"];
NSData *data = [dict objectForKey:(__bridge id)kSecValueData];
DLog(@"Password: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
DLog(@"Dictionary: %@", dict);
Here is the output, as you can see the password is null:
Password:
Dictionary: {
acct = Nikita;
agrp = "97CYSL4U6B.com.Nikita.MyApp";
cdat = "2015-03-07 08:51:35 +0000";
gena = <4e696b69 7461>;
mdat = "2015-03-07 08:51:35 +0000";
pdmn = ak;
svce = "com.Nikita.MyApp";
sync = 0;
tomb = 0;
}
Easy fix, I had to add the following key to the search dictionary. Now it returns the password correctly.
[searchDict setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.