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

时间:2013-06-04 15:44:15

标签: ios keychain

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的结果字典中使用,表示返回值的类型。

当我调用SecItemAdd来创建钥匙串项时,我应该使用哪个键?

1 个答案:

答案 0 :(得分:7)

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

此主题中的引用有点不清楚,kSecValueData键用作输出键和输入键。也就是说,在查询钥匙串项(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)];
}

添加密码:

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
}