我应该使用哪个密钥将密码存储在iOS钥匙串中?

Apple GenericKeychain示例中的KeychainItemWrapper类使用kSecValueData键来存储密码。

但是引用http://developer.apple.com/library/ios/#documentation/Security/Reference/keychainservices/Reference/reference.html#//apple_ref/doc/uid/TP30000898

kSecValueData被用在SecItemCopyMatching或SecItemAdd的结果字典中,指示返回值的types。

当我调用SecItemAdd创build一个keychain项目时,应该使用哪个键?

您应该使用kSecValue数据作为存储密码的密钥(以NSData或CFDataRef格式)。

该主题中的引用有点不清楚,kSecValueData键作为输出键和input键。 也就是说,当您查询Keychain项(SecItemCopyMatching)并指定kSecReturnAttributes项时使用它,所以结果作为字典返回,密码将存储在该字典的kSecValueData项下。 而且,当您将项目添加到钥匙串(SecItemAdd)时,您也可以使用它,在调用方法之前将密码的NSData或CFDataRef值存储在kSecValueData项中。

这是两种情况的一个例子:

检索密码:

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

添encryption码:

 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 }