iOS钥匙串中受密码保护的条目

您将拥有应用程序的名称,而不是“ keychain-sample”。

请注意,在这种情况下, SecItemCopyMatching调用是同步的,必须在后台线程上完成以防止主线程阻塞。

如果用户输入了错误的密码,那么iOS会自动重新显示提示。 在用户输入正确的密码或点击“取消”或超过允许的最大尝试次数(由系统定义的情况下,如果我没有记错的话,为5次), SecItemCopyMatching调用将不会返回。

使用LAContext.evaluateAccessControl

如果我们要手动控制尝试次数,并且还避免长时间运行阻塞调用SecItemCopyMatching则可以使用稍微不同的方法:

在这里,我们创建一个LAContext实例,并为它调用带有operation: .useItem evaluateAccessControl operation: .useItem 。 这个evaluateAccessControl调用将触发与我们之前相同的UI提示。 但是,后续的SecItemCopyMatching调用不会被阻止。

同样值得注意的是,由于这个原因, localizedReason参数在此evaluateAccessControl调用中被忽略,并且UI提示与前面的情况完全相同。

SecItemCopyMatching准备数据的关键点是将LAContext实例设置为kSecUseAuthenticationContext密钥的值,并且还为kSecUseAuthenticationUI设置kSecUseAuthenticationUIFail值。

在这种情况下,第一次尝试输入错误密码后,我们的loadPassProtected调用将失败,如果要允许第二次尝试,我们将必须手动重复该过程。 这样我们就可以控制尝试次数。

顺便说一句,如果我们在SecItemCopyMatching调用中不使用kSecUseAuthenticationUIFail ,则系统将以与以前相同的方式自动处理错误的密码。 并且SecItemCopyMatching将变得阻塞。

自定义用户界面,而不是系统提示

现在,如果系统密码提示不适用于我们的应用程序设计怎么办? 看来我们可以实现自己的用户界面来输入密码,只需将密码值提供给钥匙串API。

为此,我们必须创建一个LAContext实例,并将从用户获得的密码设置LAContext实例。 与将条目保存在钥匙串中时的方式相同:

在这里,我们还使用了非阻塞的SecItemCopyMatching调用。

还应注意,您需要一个真实的设备来测试此代码。 它在模拟器中不起作用。 我看到有人提到它在关闭密码的真实设备上不起作用,例如:

iOS钥匙串– LAContext.setCredential(data,.applicationPassword)在模拟器上返回false
似乎applicationPassword与设备的系统密码结合使用。 因此,… stackoverflow.com

但是我的测试表明,至少在iOS 12中,当我关闭设备上的密码时,它可以正常工作。

如本文中所述,用于创建和读取受密码保护的条目的示例代码可以在github上的该项目中找到:

algrid /钥匙串样本
iOS钥匙串用法示例。 通过在GitHub上创建一个帐户来为algrid / keychain-sample开发做出贡献。 github.com

我希望这些信息对提高您的iOS应用程序的安全性很有帮助。 如果您发现问题或有任何建议,请告诉我。