【发布时间】:2021-05-20 19:55:01
【问题描述】:
SecItemCopyMatching 在尝试读取物理设备 (iPhone 6S) 上的 kSecClassIdentity 钥匙串项目时返回 errSecNotAvailable,而该项目使用 kSecAccessControlUserPresence 保存。
当我运行代码时,设备要求我使用 TouchID 进行身份验证。我用手指,提示消失了,但是 SecItemCopyMatching 需要相对较长的时间才能返回,当它返回时,它会给出errSecNotAvailable。
这很奇怪,因为当我使用 LocalAuthentication(不使用钥匙串)时,TouchID 有效。如果我在没有访问控制属性的情况下保存证书,也可以检索证书。但我想使用kSecAccessControlUserPresence。知道为什么会出现错误吗?
添加证书:
- (BOOL)keychainAddIdentity:(SecIdentityRef)identity withLabel:(NSString *)label {
CFErrorRef error = NULL;
SecAccessControlRef sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault, kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly, kSecAccessControlUserPresence, &error);
NSLog(@"SecAccessControlCreateWithFlags error: %@", error); // always null
NSDictionary *attributes = @{
(id)kSecAttrLabel: label,
(id)kSecValueRef: (__bridge id)identity,
(id)kSecAttrAccessControl: (__bridge id)sacObject
};
OSStatus status = SecItemAdd((CFDictionaryRef)attributes, NULL);
[self printOSStatus:status]; // errSecSuccess
return status == errSecSuccess;
}
在读证书:
- (SecIdentityRef)keychainGetIdentityWithLabel:(NSString *)label userPromptMessage:(NSString *)message {
NSDictionary *query = @{
(id)kSecClass: (id)kSecClassIdentity,
(id)kSecAttrLabel: label,
(id)kSecReturnRef: @YES,
(id)kSecUseOperationPrompt: message
};
SecIdentityRef identity = NULL;
OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&identity);
[self printOSStatus:status]; // errSecNotAvailable
return identity;
}
测试代码:
SecIdentityRef identity = [... load certificate file ...];
BOOL certSaved = [self saveCertificate:identity]; // YES
SecIdentityRef cert = [self loadCertificate]; // (null)
所以当添加没有sacObject 的证书时,一切正常,但有了它,我得到errSecNotAvailable。为什么?
【问题讨论】:
-
你找到解决办法了吗?
-
@swalkner 抱歉,这是 5 年前的事了,我几乎不记得当时我在做什么项目。很可能我做了一些其他的工作。