简体   繁体   中英

Unable to pull password from keychain - iOS

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM