2017-01-17 3 views
-1

Мне интересно, когда вы готовитесь к Keychain item, когда бы вы конвертировали NSString в NSData?iOS Keychain: NSDate vs NSString

Например: В коде, предусмотренном настоящим учебнике http://hayageek.com/ios-keychain-tutorial/

В нем говорится следующее:

[dict setObject:encodedKey forKey:(__bridge id)kSecAttrAccount]; 

Однако, в книге "IOS Application Security" Дэвид Thiel использовал следующее:

[dict setObject:@"dthiel" forKey:(__bridge id)kSecAttrAccount]; 

Итак, я совершенно запутался, когда мне нужно, чтобы преобразовать NSString до NSData и как я могу рассказать?

спасибо.

ответ

0

Вы ДОЛЖНЫ кодировать значение как NSData.

Например:

#define KeychainIdentifier @"keychain.access.identifier" 

- (void)setKeyValue:(NSString *)key value:(NSString *)value { 
    //The keychain identifier must be encoded as `NSData`. 
    NSData *keychainItemID = [KeychainIdentifier dataUsingEncoding:NSUTF8StringEncoding]; 


    //Build the query. We need to QUERY the keychain and check if the item exists. 
    //If it does, we will NOT be adding the item in the keychain. Note: You can "overwrite" the data if you want but for this example, I'm going to keep it simple and NOT do that. 
    //For this example, the item stored is a "GenericPassword". 
    //We will query for the existence of "one" item. 
    //This query will only return attributes because we are not FETCHING from the keychain. Just "checking/querying". 
    //Finally, the item is accessible when the device is unlocked. 
    NSMutableDictionary *query = [@{ 
            (id)kSecClass    : (id)kSecClassGenericPassword, 
            (id)kSecAttrGeneric  : keychainItemID, 
            (id)kSecMatchLimit  : (id)kSecMatchLimitOne, 
            (id)kSecReturnAttributes : (id)kCFBooleanTrue, 
            (id)kSecAttrAccessible : (id)kSecAttrAccessibleWhenUnlocked, 
            (id)kSecAttrAccount  : key 
            } mutableCopy]; 


    //Query the keychain and get all the item's attributes. 
    CFMutableDictionaryRef result = nil; 
    OSStatus error = SecItemCopyMatching((__bridge CFMutableDictionaryRef)query, (CFTypeRef *)&result); 

    if (error == errSecItemNotFound) { 
     //Item does not exist, add it to the keychain. 
     //To do that, we turn our query into an "INSERT". 
     //That means we need to remove the "return" key because we are no longer fetching/querying and returning attributes. We also have to remove the match limit. 
     //We also remove the match limit. 
     [query removeObjectForKey:(id)kSecMatchLimit]; 
     [query removeObjectForKey:(id)kSecReturnAttributes]; 

     //Now we encode the data to be stored in the keychain and then we submit our "INSERT" to the keychain. This will add the item in the keychain. 
     [query setObject:[value dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData]; 

     error = SecItemAdd((__bridge CFMutableDictionaryRef)query, nil); 

     if (error == noErr) { 
      //Success. 
     } 
     else { 
      //Something went wrong. 
     } 
    } 
    else { 
     //Item already exists. 
    } 
} 
+0

Благодарим Вас за образец. Просто интересно, нужно ли ** kSecAttrGeneric **? Поскольку я помню, что ** kSecClassGenericPassword ** требуется только ** kSecClass **, ** kSecAttrAccount ** и ** kSecAttrServer ** для идентификации, это правильно? –

+0

@KwokPingLau; Это не обязательно. Это необязательно. Как вы можете видеть здесь: http://stackoverflow.com/questions/11614047/what-makes-a-keychain-item-unique-in-ios Первичный ключ для '' kSecClassGenericPassword'' - 'kSecAttrAccount и kSecAttrService' – Brandon