1

I integrated Biometrics authentication follow this guideline (https://developer.android.com/codelabs/biometric-login#2). The issue is I got this error

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:502)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 
     Caused by: javax.crypto.AEADBadTagException
        at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:517)
        at javax.crypto.Cipher.doFinal(Cipher.java:2055)
        at com.myApp.myAppName.service.CryptographyManagerImpl.decryptData(CryptographyManager.kt:89)

The CryptographyManager line 89 is

override fun decryptData(ciphertext: ByteArray, cipher: Cipher): String {
        val plaintext = cipher.doFinal(ciphertext)
        return String(plaintext, Charset.forName("UTF-8"))
    }

The way I encrypt the data is

 override fun encryptData(plaintext: String, cipher: Cipher): CiphertextWrapper {
        val ciphertext = cipher.doFinal(plaintext.toByteArray(Charset.forName("UTF-8")))
        return CiphertextWrapper(ciphertext, cipher.iv)
    }

The Cipher is initialized like this

private val ENCRYPTION_BLOCK_MODE = KeyProperties.BLOCK_MODE_GCM
private val ENCRYPTION_PADDING = KeyProperties.ENCRYPTION_PADDING_NONE
private val ENCRYPTION_ALGORITHM = KeyProperties.KEY_ALGORITHM_AES

private fun getCipher(): Cipher {
       val transformation = "$ENCRYPTION_ALGORITHM/$ENCRYPTION_BLOCK_MODE/$ENCRYPTION_PADDING"
       return Cipher.getInstance(transformation)
   }

How do I fix this issue?

Pandarian Ld
  • 727
  • 3
  • 13
  • 25
  • No idea what `CiphertextWrapper` does, but from the name it encapsulates ciphertext and IV. Has the encapsulated IV been taken into account during decryption? How is `cipher` instantiated for the two calls? The posted code is far from an [MCVE](https://stackoverflow.com/help/minimal-reproducible-example). – Topaco Apr 01 '21 at 08:08
  • @Topaco I added how Cipher is initialized. – Pandarian Ld Apr 01 '21 at 10:03
  • More interesting would be what `$ENCRYPTION_ALGORITHM` etc. is. With regard to the error message perhaps `AES/GCM/NoPadding`. In general, cipher still needs to be initialized (`init()`). This specifies (in addition to the key) the nonce/IV. Does the decryption also use the nonce/IV of the encryption? – Topaco Apr 01 '21 at 10:25
  • @Topaco Sorry for the missing information. I just added those value used in transformation string. I did not see the decryption use nonce/IV of the encryption. How do I implement that? – Pandarian Ld Apr 01 '21 at 10:32
  • During encryption a random nonce/IV is generated (for GCM 12 bytes). This is encapsulated in a `GCMParameterSpec`, which is passed to `Cipher#init()` (see [here](https://developer.android.com/reference/kotlin/javax/crypto/Cipher)). Alternatively, the nonce/IV can be _implicitly_ generated by `Cipher` and determined with `Cipher#getIV()`. When decrypting, the nonce/IV from the encryption must be applied (as with encryption, it is passed to `init()` using a `GCMParameterSpec`). The (non-secret) nonce/IV has therefore to be sent to the recipient along with the ciphertext, typically concatenated. – Topaco Apr 01 '21 at 10:52
  • @Topaco I saw the IV is used in data encryption (the method encryptData() that return CiphertextWrapper) but I did not saw any nonce/IV on cipher initialize for both encrypt and decrypt data. Therefore I need to add? or do something with IV when I decrypt the data? – Pandarian Ld Apr 01 '21 at 12:00
  • You have to use the IV of the encryption for decryption. I cannot tell you how you do this in detail for the architecture you are using. The only important thing is that the IV of the encryption, i.e. from the wrapper, is passed to the cipher for decryption. – Topaco Apr 01 '21 at 12:35
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/230660/discussion-between-pandarian-ld-and-topaco). – Pandarian Ld Apr 02 '21 at 06:22

0 Answers0