【问题标题】:Keychain returns errSecNotAvailable when using access controlKeychain 在使用访问控制时返回 errSecNotAvailable
【发布时间】: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 年前的事了,我几乎不记得当时我在做什么项目。很可能我做了一些其他的工作。

标签: ios keychain


【解决方案1】:

在将身份保存到钥匙串时,您似乎缺少 kSecClass: kSecClassIdentity 属性的键/值。如果没有在途中指定课程,我认为以后没有办法阅读它。

【讨论】:

    【解决方案2】:

    在我的背景下,钥匙串数据应该能够在应用程序启动后 200 毫秒后使用钥匙串。那么,您什么时候想要获取这些数据呢?您是否有足够的时间来获取这些数据。

    钥匙串数据也可以与您的 TouchID 或 faceID 相关联。但是,也许 iphone6s 的传感器不好(我们以前有一个,它工作得不是很好)。为确保安全,您应该尝试通过正常登录来访问此数据。

    而且我敢肯定,当它发生变化时,Apple 不会更新钥匙串数据文档。我遇到了一些与钥匙串相关的场景,有时苹果文档有错误的信息。 (例如wrong keychain info in Apple document

    因此,您的工作并不轻松,请尝试以上建议。如果它不起作用,请尝试另一种方法来满足您的要求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-19
      • 2020-10-20
      • 2017-07-08
      • 2015-10-16
      • 1970-01-01
      • 2014-08-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多