keychain在kSecValueData中存放Dictionary

我使用的是apple 上提供的sample code KeychainItemWrapper 在此基础上进行修改

相关链接:

http://useyourloaf.com/blog/2010/04/28/keychain-duplicate-item-when-adding-password.html

http://stackoverflow.com/questions/4891562/ios-keychain-services-only-specific-values-allowed-for-ksecattrgeneric-key

http://stackoverflow.com/questions/7249297/convert-nsdictionary-to-nsdata

1.在keychain的kSecValueData中存储的数据必须是NSData类型,否则无法存储。所以就需要将NSDictionary转换成NSData

- (NSMutableDictionary *)dictionaryToSecItemFormat:(NSDictionary *)dictionaryToConvert
{
    // The assumption is that this method will be called with a properly populated dictionary
    // containing all the right key/value pairs for a SecItem.
    
    // Create a dictionary to return populated with the attributes and data.
    NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];
    
    // Add the Generic Password keychain item class attribute.
    [returnDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
    
    // Convert the NSString to NSData to meet the requirements for the value type kSecValueData.
	// This is where to store sensitive data that should be encrypted.

    NSMutableData *data = [[NSMutableData alloc] init];
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    [archiver encodeObject:[dictionaryToConvert objectForKey:(id)kSecValueData] forKey:@"Some Key Value"];
    [archiver finishEncoding];
    [archiver release];
    

    
    // Here, data holds the serialized version of your dictionary
    // do what you need to do with it before you:
    [returnDictionary setObject:data forKey:(id)kSecValueData];
    [data release];
    return returnDictionary;
}
2.取数据时需要将NSData 转换成NSDictionary
- (NSMutableDictionary *)secItemFormatToDictionary:(NSDictionary *)dictionaryToConvert
{
    // The assumption is that this method will be called with a properly populated dictionary
    // containing all the right key/value pairs for the UI element.
    
    // Create a dictionary to return populated with the attributes and data.
    NSMutableDictionary *returnDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];
    
    // Add the proper search key and class attribute.
    [returnDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
    [returnDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
    
    // Acquire the password data from the attributes.
    NSData *passwordData = NULL;
    //NSMutableDictionary *passwordData = nil;
    if (SecItemCopyMatching((CFDictionaryRef)returnDictionary, (CFTypeRef *)&passwordData) == noErr)
    {
        // Remove the search, class, and identifier key/value, we don't need them anymore.
        [returnDictionary removeObjectForKey:(id)kSecReturnData];
        
        // Add the password to the dictionary, converting from NSData to NSString.
        NSData *d = [[NSMutableData alloc] initWithData:passwordData];
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:d];
        NSDictionary *myDictionary = [[unarchiver decodeObjectForKey:@"Some Key Value"] retain];
        [unarchiver finishDecoding];
        [unarchiver release];
        [returnDictionary setObject:myDictionary forKey:(id)kSecValueData];
        [d release];
    }
    else
    {
        // Don't do anything if nothing is found.
        NSAssert(NO, @"Serious error, no matching item found in the keychain.\n");
    }
    
    [passwordData release];
   
	return returnDictionary;
}
3.更改genericPasswordQuery、keychainItemData属性
[self.genericPasswordQuery setObject:identifier forKey:(id)kSecAttrAccount];

[self.keychainItemData setObject:identifier forKey:(id)kSecAttrAccount];

你可能感兴趣的:(ios,Keychain)