Аутентификация по отпечатку пальца в Android 6.0 с использованием ошибок setUserAuthentication(true)
У меня есть реализация аутентификации по отпечатку пальца, которая работала нормально, пока я не запустил ее на HTC M9+ (Android 6.0).
У меня есть ключ, сгенерированный в AndroidKeyStore:
mKeyPairGenerator.initialize(
new KeyGenParameterSpec.Builder(KEY_ALIAS, KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_ENCRYPT)
.setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
.setUserAuthenticationRequired(true)
.build());
mKeyPairGenerator.generateKeyPair();
Затем я пытаюсь использовать это для инициализации шифра для вызова аутентификации по отпечатку пальца, и на HTC под управлением 6.0 Android я получаю сообщение об ошибке:
Crypto primitive not backed by AndroidKeyStore provider
Теперь я понимаю, что в API 23 есть ошибка, которая не позволяет использовать открытый ключ без аутентификации (хотя это и должно быть), поэтому я реализовал код для извлечения ключа из элемента AndroidKeyStore и затем его инициализации (согласно предложению в Android документация). Это работает просто отлично.
Но я не могу использовать этот извлеченный объект шифрования / шифрования с открытым ключом для вызова аутентификации отпечатка пальца:
m_fingerprintManager.authenticate(m_cryptoObject, m_cancellationSignal, 0, this, null)
Если я не извлекаю открытый ключ для init и использую его прямо из AndroidKeyStore, я получаю сообщение об ошибке, подтверждающее, что пользователь не аутентифицирован.
Вот код для initCipher, извлекающего открытый ключ:
PublicKey key = mKeyStore.getCertificate(KEY_ALIAS).getPublicKey();
PublicKey unrestricted = KeyFactory.getInstance(key.getAlgorithm())
.generatePublic(new X509EncodedKeySpec(key.getEncoded()));
OAEPParameterSpec spec = new OAEPParameterSpec(
"SHA-256", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);
mCipher.init(opmode, unrestricted, spec);
Вот код, взятый прямо из хранилища ключей:
PrivateKey key = (PrivateKey) mKeyStore.getKey(KEY_ALIAS, null);
mCipher.init(opmode, key);
Использование извлеченного публичного файла возвращает ошибку, что он не поддерживается AndroidKeyStore.
Использование ключа непосредственно из хранилища возвращает ошибку о том, что пользователь не аутентифицирован.
Итак, как мне заставить это работать? Как уже упоминалось, использование ключа непосредственно из хранилища ключей отлично работало на других устройствах (Samsung S7 Edge с Android M и N, Nexus 6P с N, Samsung S6 с M (6.0.1) и другие)