我已经成功地分别使用钥匙串和钥匙串共享(在多个设备之间同步钥匙串项目)实现了 TouchID。当我尝试同时执行它们时,我收到错误“-50”,这是无效参数。从下面的代码中,删除kSecAttrAccessControl或kSecAttrSynchronizable可以按预期工作。
根据我迄今为止的经验(阅读 - 几天的挫败感),以及一些钥匙串 API 简化工具(如UICKeychainStore )的功能,似乎如果我使用 Touch ID 身份验证,钥匙串共享将不起作用,反之亦然。我正在寻找可以说明但无法找到的 Apple 文档。
我浏览了 Apple 的SecItem.h页面,我发现一个有用的信息说明了以下关于kSecAttrAccessible和kSecAttrSynchronizable的信息:“如果在 OS X 或 iOS 上同时指定了这两个属性,则 kSecAttrAccessible 键的值可能只是其名称不以“ThisDeviceOnly”结尾,因为它们无法同步到另一台设备。” 但是,我没有使用“ThisDeviceOnly”(我目前正在使用kSecAttrAccessibleAlways进行测试)
您能否帮助指出 Apple 是否以及在何处记录了此限制?这将有助于我将其记录下来,然后继续前进。谢谢。
- (void)addKeychainItemWithIdentifier:(NSString *)identifier andData:(NSData *)data {
CFErrorRef error = NULL;
SecAccessControlRef sacObject;
sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
kSecAttrAccessibleAlways,
kSecAccessControlUserPresence, &error);
if(sacObject == NULL || error != NULL)
{
NSString *msg0 = [NSString stringWithFormat:NSLocalizedString(@"SEC_ITEM_ADD_CAN_CREATE_OBJECT", nil), error];
[self printResultWithMessage:msg0];
return;
}
NSDictionary *attributes = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecValueData: data,
(__bridge id)kSecAttrAccessible:(__bridge id)kSecAttrAccessibleAlways,
(__bridge id)kSecAttrService: identifier,
(__bridge id)kSecAttrSynchronizable:(__bridge id)kCFBooleanTrue,
(__bridge id)kSecAttrAccessControl: (__bridge_transfer id)sacObject
};
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)attributes, nil);
NSError *statuserror = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil];
[self printResultWithMessage:[self keychainErrorToString:status]];
});
}