Apple, iOS 13, CryptoKit, Secure Enclave - принудительное использование биометрической аутентификации перед использованием закрытого ключа
Я работаю с новой библиотекой Cryptokit от Apple и пытаюсь заставить работать базовый вариант использования.
Цель: я хотел бы создать закрытый ключ в безопасном анклаве с помощью криптокита, сохранить ссылку на ключ в цепочке ключей устройства iOS и убедиться, что ключ может быть повторно инициализирован в безопасном анклаве только после того, как пользователь аутентифицировал себя с помощью некоторых биометрических данных. Метод аутентификации.
Текущее состояние: пока что я могу инициализировать закрытый ключ в безопасном анклаве с помощью следующего кода:
var privateKeyReference = try CryptoKit.SecureEnclave.P256.KeyAgreement.PrivateKey.init();
Кроме того, я могу сохранять и извлекать соответствующую ссылку на закрытый ключ из цепочки ключей. После получения ссылки я могу повторно инициализировать закрытый ключ в безопасном анклаве с помощью следующего кода:
var privateKeyReference = getPrivateKeyReferenceFromKeyChain();
var privateKey = try CryptoKit.SecureEnclave.P256.KeyAgreement.PrivateKey.init(
dataRepresentation: privateKeyReference
);
Пока все работает, как ожидалось, и все криптографические операции с закрытым ключом проходят успешно.
Теперь, насколько я понимаю запасную документацию 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
);
Таким образом, гарантируется, что закрытый ключ может быть повторно инициализирован только тогда, когда пользователь аутентифицирует себя с помощью некоторого метода биометрической аутентификации. Стиль начальной инициализации работает без ошибок.
Проблема: однако, добавив предыдущий код, я не получаю никаких запросов на биометрическую аутентификацию и не могу использовать закрытый ключ после повторной инициализации. Следующая ошибка регистрируется всякий раз, когда я пытаюсь выполнить какую-либо криптографическую операцию с повторно инициализированным ключом, например, подписание:
Error Domain=CryptoTokenKit Code=-9 "setoken: unable to sign digest" UserInfo={NSLocalizedDescription=setoken: unable to sign digest})
Насколько я мог догадаться отсюда, я думаю, чтоCode=-9
относится к ошибке "Требуется аутентификация".
Вопрос: Может ли кто-нибудь указать мне какую-либо документацию или учебное пособие, как достичь того, что я ищу, или объяснить мне, чего мне не хватает?
Спасибо!
Перекрестная публикация: https://forums.developer.apple.com/message/387746
1 ответ
После нескольких дней терпения я смог получить ответ от службы поддержки разработчиков Apple. Они предложили следующий метод, который лишь немного отличается от моего подхода:
var error: Unmanaged<CFError>? = nil;
let accessCtrl = SecAccessControlCreateWithFlags(
nil,
kSecAttrAccesibleAfterFirstUnlockThisDeviceOnly,
[.privateKeyUsage, .biometryCurrentSet],
&error
);
var privateKeyReference = try CryptoKit.SecureEnclave.P256.KeyAgreement.PrivateKey.init(
accessControl: accessCtrl
);
Кроме того, пока что версия iOS 13.1.3
был выпущен, и после обновления моего устройства вышеуказанный код начал работать. Так что либо между моим кодом и кодом Apple есть небольшая разница, либо это связано с обновлением. Тем не менее, сейчас он работает.