无法从钥匙串中提取密码 - iOS

Unable to pull password from keychain - iOS

我有以下创建钥匙串项并使用 SecItemAdd() 将其添加到钥匙串的方法。当我尝试取回密码时,我无法在我的控制台中看到它。我在设备上 运行,而不是模拟器。

- (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;

}

这是我测试上述方法的代码:

[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);

这是输出,您可以看到密码为空:

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;
}

很容易修复,我必须将以下键添加到搜索字典中。现在 returns 密码正确了。

[searchDict setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];