简体   繁体   中英

Apple, iOS 13, CryptoKit, Secure Enclave - Enforce biometric authentication ahead of private key usage

I am working with Apple's new cryptokit library and am trying to get a basic use case to work.

Goal : I would like to create a private key in the secure enclave via the cryptokit, store the key's reference in the iOS device's key chain and ensure that the key can only be reinitialized in the secure enclave after the user has authenticated himself via some biometric authentication method.

Current state : So far, I am able to initialize a private key in the secure enclave via the following code:

var privateKeyReference = try CryptoKit.SecureEnclave.P256.KeyAgreement.PrivateKey.init();

Furthermore, I can store and retrieve the corresponding private key's reference from the key chain. After retrieving the reference, I can reinitialize the private key in the secure enclave with the following code:

var privateKeyReference = getPrivateKeyReferenceFromKeyChain();
var privateKey = try CryptoKit.SecureEnclave.P256.KeyAgreement.PrivateKey.init(
   dataRepresentation: privateKeyReference
);

So far everything works as expected and all cryptographic operations with the private key succeed.

Now, as far as I understand the spare documentation by Apple , I should be able to modify the first initialization of the private key to something as follows.

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
);

Thereby, ensuring that the private key can only be reinitialized, when the user authenticates himself via some biometric authentication method. The initial initialization stil works without any errors.

Problem : However, adding the previous code, I do not get any biometric authentication prompt and can not use the private key at all after reinitialization. The following error is logged whenever I try to execute some cryptographic operation with the reinitialized key, here for example some signing:

Error Domain=CryptoTokenKit Code=-9 "setoken: unable to sign digest" UserInfo={NSLocalizedDescription=setoken: unable to sign digest})

As far as I could guess from here , I think that Code=-9 refers to the "authenticationNeeded" error.

Question : Can someone point me to some documentation or tutorial how to achieve what I am looking for or explain to me what I am missing?

Thanks!

Cross-Post: https://forums.developer.apple.com/message/387746

After a couple of days of patience I was able to obtain an answer from the Apple development support. They suggested the following method which only differs a little bit from my approach:

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

Additionally, in the meantime iOS version 13.1.3 was released and, after upgrading my device, the above code started working. So either there is a subtle difference between mine and Apple's code or it is related to the update. Nevertheless, it is working now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM