Apple、iOS 13、CryptoKit、Secure Enclave - 在使用私钥之前强制执行生物识别身份验证

Rob*_*bin 7 cryptography ios swift apple-cryptokit

我正在使用 Apple 的新 cryptokit 库,并试图获得一个基本的用例来工作。

目标:我想通过 cryptokit 在安全飞地中创建私钥,将密钥的引用存储在 iOS 设备的钥匙链中,并确保只有在用户通过某种生物识别技术对自己进行身份验证后才能在安全飞地中重新初始化密钥身份验证方法。

当前状态:到目前为止,我可以通过以下代码在安全飞地中初始化私钥:

var privateKeyReference = try CryptoKit.SecureEnclave.P256.KeyAgreement.PrivateKey.init();
Run Code Online (Sandbox Code Playgroud)

此外,我可以从钥匙链中存储和检索相应私钥的引用。检索引用后,我可以使用以下代码重新初始化安全飞地中的私钥:

var privateKeyReference = getPrivateKeyReferenceFromKeyChain();
var privateKey = try CryptoKit.SecureEnclave.P256.KeyAgreement.PrivateKey.init(
   dataRepresentation: privateKeyReference
);
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切都按预期进行,并且所有使用私钥的加密操作都成功。

现在,据我了解Apple 的备用文档,我应该能够将私钥的第一次初始化修改为如下所示。

let authContext = LAContext();
let accessCtrl = SecAccessControlCreateWithFlags(
   kCFAllocatorDefault,
   kSecAttrAccesibleWhenUnlockedThisDeviceOnly,
   [.privateKeyUsage, .userPresence, .biometryCurrentSet],
   nil
);
var privateKeyReference = try CryptoKit.SecureEnclave.P256.KeyAgreement.PrivateKey.init(
   accessControl: accessCtrl!,
   authenticationContext: authContext
);
Run Code Online (Sandbox Code Playgroud)

从而,确保只有当用户通过某种生物特征认证方法对自己进行身份验证时,私钥才能被重新初始化。初始初始化仍然有效,没有任何错误。

问题:但是,添加前面的代码后,我没有收到任何生物识别身份验证提示,并且在重新初始化后根本无法使用私钥。每当我尝试使用重新初始化的密钥执行某些加密操作时,都会记录以下错误,例如此处的一些签名:

Error Domain=CryptoTokenKit Code=-9 "setoken: unable to sign digest" UserInfo={NSLocalizedDescription=setoken: unable to sign digest})
Run Code Online (Sandbox Code Playgroud)

据我从这里猜测,我认为这Code=-9是指“authenticationNeeded”错误。

问题:有人可以向我指出一些文档或教程如何实现我正在寻找的东西或向我解释我缺少什么吗?

谢谢!

交叉发布: https: //forums.developer.apple.com/message/387746

Rob*_*bin 3

经过几天的耐心等待,我从苹果开发支持那里得到了答案。他们建议了以下方法,与我的方法仅略有不同:

var error: Unmanaged<CFError>? = nil;
let accessCtrl = SecAccessControlCreateWithFlags(
   nil,
   kSecAttrAccesibleAfterFirstUnlockThisDeviceOnly,
   [.privateKeyUsage, .biometryCurrentSet],
   &error
);
var privateKeyReference = try CryptoKit.SecureEnclave.P256.KeyAgreement.PrivateKey.init(
   accessControl: accessCtrl
);
Run Code Online (Sandbox Code Playgroud)

另外,与此同时,iOS 版本13.1.3发布了,在升级我的设备后,上述代码开始工作。所以要么我的代码和苹果的代码有细微的差别,要么与更新有关。尽管如此,它现在正在发挥作用。