使用访问控制时,Keychain返回errSecNotAvailable

时间:2015-11-03 06:37:47

标签: ios keychain

当项目与SecItemCopyMatching一起保存时,

errSecNotAvailable在物理设备(iPhone 6S)上尝试阅读kSecClassIdentity钥匙串项时会返回kSecAccessControlUserPresence

当我运行代码时,设备会要求我使用TouchID进行身份验证。我使用我的手指并且提示消失,但是然后SecItemCopyMatching返回需要相对较长的时间,当它发生时,它会给出errSecNotAvailable

这很奇怪,因为当我使用LocalAuthentication(不使用Keychain)时,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。为什么呢?

1 个答案:

答案 0 :(得分:0)

在将标识保存到钥匙串时,您似乎缺少kSecClass:kSecClassIdentity属性的键/值。如果没有在路上指定课程,我认为以后没有任何方法可以阅读。