2013-06-04 8 views
6

Die KeychainItemWrapper-Klasse im Apple GenericKeychain-Beispiel verwendet den Schlüssel kSecValueData zum Speichern des Kennworts.Welchen Schlüssel sollte ich verwenden, um das Passwort im iOS-Schlüsselbund zu speichern?

Aber die Referenz http://developer.apple.com/library/ios/#documentation/Security/Reference/keychainservices/Reference/reference.html#//apple_ref/doc/uid/TP30000898

sagt kSecValueData im Ergebnis Wörterbuch für SecItemCopyMatching oder SecItemAdd, verwendet wird, ist die Art des Wertes zurückgegeben angibt.

Welchen Schlüssel sollte ich verwenden, wenn ich SecItemAdd zum Erstellen eines Schlüsselbundelements aufruft?

Antwort

7

Sie sollten kSecValue-Daten als Schlüssel zum Speichern des Kennworts (im NSData- oder CFDataRef-Format) verwenden.

Der Verweis ist in diesem Thema ein wenig unklar, kSecValueData Schlüssel funktioniert als Ausgabeschlüssel sowie Eingabe-Schlüssel. Das heißt, Sie verwenden es, wenn Sie ein Schlüsselbundelement (SecItemCopyMatching) abfragen und einen kSecReturnAttributes-Schlüssel angeben, damit das Ergebnis als Wörterbuch zurückgegeben wird. Das Kennwort wird unter einem kSecValueData-Schlüssel dieses Wörterbuchs gespeichert. Und Sie verwenden es auch, wenn Sie dem Schlüsselbund ein Element hinzufügen (SecItemAdd) und den Wert NSData oder CFDataRef Ihres Kennworts vor dem Aufruf der Methode im Schlüssel kSecValueData speichern.

Hier ist ein Beispiel für beide Fälle:

Suchen Passwort:

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

Hinzufügen Passwort:

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

Bessere Code, mit weniger Fehlern, hier: http://stackoverflow.com/questions/19284063/secitemcopymatching-returns-nil-data –

Verwandte Themen