2013-06-04 4 views
6

La classe KeychainItemWrapper nell'esempio di Apple GenericKeychain utilizza la chiave kSecValueData per memorizzare la password.quale chiave dovrei usare per memorizzare la password nel portachiavi iOS?

Ma il riferimento http://developer.apple.com/library/ios/#documentation/Security/Reference/keychainservices/Reference/reference.html#//apple_ref/doc/uid/TP30000898

dice kSecValueData è utilizzato nel dizionario risultati per SecItemCopyMatching o SecItemAdd, che indica il tipo di valori restituiti.

quale chiave devo usare quando chiamo SecItemAdd per creare un oggetto portachiavi?

risposta

7

È necessario utilizzare i dati kSecValue come chiave per memorizzare la password (nel formato NSData o CFDataRef).

Il riferimento è un po 'poco chiaro in questo argomento, chiave kSecValueData funziona come chiave di output e chiave di input. Cioè, lo si utilizza quando si esegue una query su un oggetto portachiavi (SecItemCopyMatching) e si specifica una chiave kSecReturnAttributes, quindi il risultato viene restituito come dizionario, la password verrà archiviata in una chiave kSecValueData del dizionario. E lo usi anche quando aggiungi un elemento al portachiavi (SecItemAdd), memorizzando il valore NSData o CFDataRef della tua password nella chiave kSecValueData prima di chiamare il metodo.

Ecco un esempio di entrambi i casi:

Recupero password

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

Aggiunta la password

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

codice migliore, con meno bug, qui: http://stackoverflow.com/questions/19284063/secitemcopymatching-returns-nil-data –