Вы должны использовать данные kSecValue в качестве ключа для хранения пароля (в формате NSData или CFDataRef).
Ссылка немного неясна в этом вопросе, ключ kSecValueData работает как выходной ключ, так и входной ключ. То есть вы используете его, когда вы запрашиваете элемент keychain (SecItemCopyMatching) и указываете ключ kSecReturnAttributes, поэтому результат возвращается как словарь, пароль будет храниться под ключом kSecValueData этого словаря. И вы также используете его, когда вы добавляете элемент в цепочку ключей (SecItemAdd), сохраняя значение NSData или CFDataRef своего пароля в ключе kSecValueData перед вызовом метода.
Вот пример обоих случаях:
Получение пароля:
NSMutableDictionary *queryDictionary = [[NSMutableDictionary alloc] init];
[queryDictionary setObject: (__bridge id)kSecClassGenericPassword forKey: (__bridge id<NSCopying>)kSecClass];
[queryDictionary setObject:service forKey:kSecAttrService];
[queryDictionary setObject:account forKey:kSecAttrAccount];
// The result will be a dictionary containing the password attributes...
[queryDictionary setObject:YES forKey:(__bridge id<NSCopying>)(kSecReturnAttributes)];
// ...one of those attributes will be a kSecValueData with the password
[queryDictionary setObject:YES forKey:(__bridge id<NSCopying>)(kSecReturnData)];
OSStatus sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)(queryDictionary), (CFTypeRef *)&result);
if (sanityCheck != noErr)
{
NSDictionary * resultDict = (__bridge NSDictionary *)result;
// here's the queried password value
NSData *passwordValue = [resultDict objectForKey:(__bridge id)(kSecValueData)];
}
Добавление пароля:
NSString *passwordString = @"my password value";
NSData *passwordData = [passwordString dataUsingEncoding:NSUTF8StringEncoding];
CFDictionaryRef result = nil;
NSMutableDictionary *addDictionary = [[NSMutableDictionary alloc] init];
[addDictionary setObject: (__bridge id)kSecClassGenericPassword forKey: (__bridge id<NSCopying>)kSecClass];
[addDictionary setObject:service forKey:kSecAttrService];
[addDictionary setObject:account forKey:kSecAttrAccount];
// here goes the password value
[addDictionary setObject:passwordData forKey:(__bridge id<NSCopying>)(kSecValueData)];
OSStatus sanityCheck = SecItemAdd((__bridge CFDictionaryRef)(queryDictionary), NULL)
if (sanityCheck != noErr)
{
// if no error the password got successfully stored in the keychain
}
Лучше код, с меньшим количеством ошибок, здесь: HTTP://stackoverflow.com/questions/19284063/secitemcopymatching-returns-nil-data –