BiometricPrompt: как зашифровать несколько строк?
Мне нужно зашифровать несколько строк с использованием биометрической аутентификации в моем приложении. Я использую этот код:
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle("Title")
.setSubtitle("subtitle")
.setDescription("description")
.setNegativeButtonText("button")
.build()
val cryptoObject = BiometricPrompt.CryptoObject(getEncryptCipher())
val biometricPrompt = BiometricPrompt(requireActivity(), Executors.newSingleThreadExecutor(), object : BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
val encodedString1 = Base64.encodeToString(result.cryptoObject?.cipher!!.doFinal(string1), Base64.DEFAULT)
val encodedString2 = Base64.encodeToString(result.cryptoObject?.cipher!!.doFinal(string2), Base64.DEFAULT) // <- I got a crash in this line
save(encodedString1, encodedString2)
}
})
biometricPrompt.authenticate(promptInfo, cryptoObject)
fun getEncryptCipher(): Cipher {
var keyStore: KeyStore = KeyStore.getInstance("AndroidKeyStore")
keyStore.load(null)
if (!isKeyExists()) {
createKey()
}
val key = keyStore.getKey("MyKeyAlias", null)
val cipher = Cipher.getInstance("${KeyProperties.KEY_ALGORITHM_AES}/${KeyProperties.BLOCK_MODE_CBC}/${KeyProperties.ENCRYPTION_PADDING_PKCS7}")
cipher.init(Cipher.ENCRYPT_MODE, key)
return cipher
}
fun createKey() {
val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, PROVIDER_ANDROID_KEYSTORE)
val builder = KeyGenParameterSpec.Builder("MyKeyAlias", KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_CBC)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
.setUserAuthenticationRequired(true)
keyGenerator.init(builder.build())
keyGenerator.generateKey()
}
Первая строка хорошо закодирована. Но когда я пытаюсь кодировать вторую строку, у меня происходит сбой:
java.lang.IllegalStateException: IV has already been used. Reusing IV in encryption mode violates security best practices.
at android.security.keystore.AndroidKeyStoreUnauthenticatedAESCipherSpi.addAlgorithmSpecificParametersToBegin(AndroidKeyStoreUnauthenticatedAESCipherSpi.java:244)
at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:237)
at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:495)
at javax.crypto.Cipher.doFinal(Cipher.java:2055)
at com.me.myapp.MyFragment$MyMethod$biometricPrompt$1.onAuthenticationSucceeded(MyFragment.kt:49)
at androidx.biometric.BiometricFragment$2$2.run(BiometricFragment.java:109)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Как я понимаю, я должен использовать разные IV для каждой строки. Но как установить новый IV? Я только что получил IV от BiometricPrompt.
1 ответ
Вы можете добавить IvParameterSpec
параметр для cipher.init
, Конечно, это, вероятно, означает, что вы должны рефакторинг getEncryptCipher
и позвонить cipher.init
впоследствии
val encodedString2 = Base64.encodeToString(result.cryptoObject?.cipher!!.doFinal(string2), Base64.DEFAULT) // <- I got a crash in this line
Вы пытаетесь сделать слишком много в этой линии; Его трудно читать, и это не повлияет на производительность, если вы введете одну или две переменные.