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 есть небольшая разница, либо это связано с обновлением. Тем не менее, сейчас он работает.

Другие вопросы по тегам