【问题标题】:BiometricPrompt: how to encrypt few strings?BiometricPrompt:如何加密几个字符串?
【发布时间】:2019-09-22 06:43:33
【问题描述】:

我需要在我的应用程序中使用生物特征身份验证加密几个字符串。我正在使用此代码:

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?我刚刚收到来自 BiometricPrompt 的静脉注射。

【问题讨论】:

  • 您是否尝试删除init?我尝试查找文档,但我猜 Google 不相信它。请注意,Cipher(愚蠢地)已被描述为重用文档中的 IV。如果您重新签发BiometricPrompt,会发生什么情况?也许它会立即返回?

标签: android kotlin cryptography aes android-biometric-prompt


【解决方案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

你在这行做的太多了;它既难以阅读,而且如果您引入一个或两个变量,它不会对性能产生任何影响。

【讨论】:

  • 对不起,可读性不好,这只是一个测试代码。 IvParameterSpec 在这种情况下不适用。我可以在 BiometricPrompt 显示之前设置它。它的工作方式相同 - 仅在第一个字符串和 string2 上我收到相同的崩溃。
猜你喜欢
  • 1970-01-01
  • 2011-12-07
  • 1970-01-01
  • 1970-01-01
  • 2012-03-08
  • 2010-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多