2013-06-04 2 views
6

Класс KeychainItemWrapper в образце Apple GenericKeychain использует ключ kSecValueData для хранения пароля.Какой ключ следует использовать для хранения пароля в iOS-брелка?

Но ссылка http://developer.apple.com/library/ios/#documentation/Security/Reference/keychainservices/Reference/reference.html#//apple_ref/doc/uid/TP30000898

говорит kSecValueData является используется в словаре результатов для SecItemCopyMatching или SecItemAdd, указывающий тип возвращаемых значений.

какой ключ следует использовать, когда я вызываю SecItemAdd для создания элемента keychain?

ответ

7

Вы должны использовать данные 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 
} 
+0

Лучше код, с меньшим количеством ошибок, здесь: HTTP://stackoverflow.com/questions/19284063/secitemcopymatching-returns-nil-data –

Смежные вопросы