我使用的是apple 上提供的sample code KeychainItemWrapper 在此基礎上進行修改 html
相關連接: ios
http://useyourloaf.com/blog/2010/04/28/keychain-duplicate-item-when-adding-password.html app
http://stackoverflow.com/questions/7249297/convert-nsdictionary-to-nsdata ui
1.在keychain的kSecValueData中存儲的數據必須是NSData類型,不然沒法存儲。因此就須要將NSDictionary轉換成NSData this
- (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];