ios - 我应该使用哪个 key 将密码存储在 iOS 钥匙串(keychain)中?

标签 ios keychain

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

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

说 kSecValueData 是 在 SecItemCopyMatching 或 SecItemAdd 的结果字典中使用,指示返回值的类型。

调用 SecItemAdd 创建钥匙串(keychain)项目时应该使用哪个 key ?

最佳答案

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

这个主题中的引用有点不清楚,kSecValueData 键既可以作为输出键,也可以作为输入键。也就是说,当您查询钥匙串(keychain)项 (SecItemCopyMatching) 并指定 kSecReturnAttributes 键时使用它,因此结果作为字典返回,密码将存储在该字典的 kSecValueData 键下。当您将项目添加到钥匙串(keychain) (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
}

关于ios - 我应该使用哪个 key 将密码存储在 iOS 钥匙串(keychain)中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16922081/

相关文章:

ios - 钥匙串(keychain)和 NSUserDefault 之间的区别?

ios - 捕获图像时出现AVCapturePhotoCaptureDelegate错误

iphone - 如何在调试期间在 iPad 中保持相同的 iPhone 应用尺寸

ios - 为什么我的代码无法填充字典(和表格 View )?

objective-c - 以编程方式从 Mac 钥匙串(keychain)存储和检索私钥

ios - 将任何对象保存到钥匙串(keychain)

ios - Firebase 异步查询

ios - 为现有的 GitHub 存储库创建 CocoaPod

ios - 无法在 Keychain Xcode 8 GM (Swift 3) 中存储数据

swift - macOS 钥匙串(keychain)共享绕过密码对话框