在android中尝试解密时出现AES BadTag异常

在android中尝试解密时出现AES BadTag异常,android,kotlin,encryption,aes,Android,Kotlin,Encryption,Aes,我正在尝试使用AES加密对一个简单字符串进行加密。 目前,我正在使用KeyGenerator生成secrect密钥,并使用Secure random生成一个16字节的随机IV 问题是,当我运行此代码时: @RequiresApi(Build.VERSION_CODES.M) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) se

我正在尝试使用AES加密对一个简单字符串进行加密。 目前,我正在使用
KeyGenerator
生成secrect密钥,并使用
Secure random
生成一个16字节的随机IV

问题是,当我运行此代码时:

  @RequiresApi(Build.VERSION_CODES.M)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val random = SecureRandom()
        val iv = ByteArray(12)
        random.nextBytes(iv)
        aesKeystoreAESWrapper = AES_WRAPPER()
        aesKeystoreAESWrapper.createSymmetricKey()
        val teste = aesKeystoreAESWrapper.encrypt("OLA MALTA", iv)
        val result = aesKeystoreAESWrapper.decrypt(teste, iv)


        ola.text = result

    }

我得到一个运行时执行选项:
javax.crypto.AEADBadTagException

我不知道问题出在哪里,我尝试在多个网站上搜索,但找不到awnser

这是我的AES代码:

class AES_WRAPPER {

    fun ByteArray.fromBytetoString() = String(this,Charsets.UTF_8)
    companion object{
        const val AES_NOPAD_TRANS = "AES/GCM/NoPadding" //Format - ”Algorithm/Mode/Padding”
        const val ANDROID_KEYSTORE = "AndroidKeyStore"
        const val KEY_ALIAS = "Keyalaisasf"
    }

    private fun createKeyStore(): KeyStore {
        val keyStore = KeyStore.getInstance(ANDROID_KEYSTORE)
        keyStore.load(null)
        return keyStore
    }

    @RequiresApi(23)
    fun createSymmetricKey() : SecretKey {
        try{
            val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEYSTORE)

            val keyGenParameterSpec = KeyGenParameterSpec.Builder(
                KEY_ALIAS,
                KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                .setRandomizedEncryptionRequired(false)
                .build()
            keyGenerator.init(keyGenParameterSpec)
            return keyGenerator.generateKey()
        } catch (e: NoSuchAlgorithmException) {
            throw RuntimeException("Failed to create a symmetric key", e)
        } catch (e: NoSuchProviderException) {
            throw RuntimeException("Failed to create a symmetric key", e)
        } catch (e: InvalidAlgorithmParameterException) {
            throw RuntimeException("Failed to create a symmetric key", e)
        }
    }

    fun encrypt(data: String, initVector: ByteArray) : ByteArray{
        val iv = GCMParameterSpec(128, initVector)

        val cipher = Cipher.getInstance(AES_NOPAD_TRANS)
        cipher.init(Cipher.ENCRYPT_MODE, getSymmetricKey(), iv)

        val encrypted = cipher.doFinal(data.toByteArray())

        return encrypted
    }

    fun decrypt(data: ByteArray, initVector: ByteArray) : String{
        val iv = GCMParameterSpec(128, initVector)

        val cipher = Cipher.getInstance(AES_NOPAD_TRANS)
        cipher.init(Cipher.DECRYPT_MODE, getSymmetricKey(), iv)

        val decrypted = cipher.doFinal(data)

        return decrypted.fromBytetoString()
    }

    @SuppressLint("NewApi")
    fun getSymmetricKey(): SecretKey {
        /*val keysore = keyStore.getEntry(KEY_ALIAS, null) as KeyStore.SecretKeyEntry
        return keysore.secretKey*/

        val keyStore = createKeyStore()

        if(!isKeyExists(keyStore)){
            createSymmetricKey()
        }

        return keyStore.getKey(KEY_ALIAS,null) as SecretKey
    }

    fun isKeyExists(keyStore : KeyStore): Boolean {
        val aliases = keyStore.aliases()
        while (aliases.hasMoreElements()) {
            return (KEY_ALIAS == aliases.nextElement())
        }
        return false
    }

}
更新,日志猫:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: io.github.andre00nogueira.myapplication, PID: 10135
    java.lang.RuntimeException: Unable to start activity ComponentInfo{io.github.andre00nogueira.myapplication/io.github.andre00nogueira.myapplication.MainActivity}: javax.crypto.AEADBadTagException
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        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 io.github.andre00nogueira.myapplication.WRAPPER.decrypt(WRAPPER.kt:73)
        at io.github.andre00nogueira.myapplication.MainActivity.onCreate(MainActivity.kt:29)
        at android.app.Activity.performCreate(Activity.java:7802)
        at android.app.Activity.performCreate(Activity.java:7791)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7356) 
        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: android.security.KeyStoreException: Signature/MAC verification failed
        at android.security.KeyStore.getKeyStoreException(KeyStore.java:1292)
        at android.security.keystore.KeyStoreCryptoOperationChunkedStreamer.doFinal(KeyStoreCryptoOperationChunkedStreamer.java:224)
        at android.security.keystore.AndroidKeyStoreAuthenticatedAESCipherSpi$BufferAllOutputUntilDoFinalStreamer.doFinal(AndroidKeyStoreAuthenticatedAESCipherSpi.java:373)
        at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineDoFinal(AndroidKeyStoreCipherSpiBase.java:506)

该问题是由
isKeyExists()
函数引起的,该函数应检查密钥库中是否包含
KEY\u ALIAS
。但是,当前的实现仅将
alias.nextElement()
找到的第一个别名与
KEY\u alias
进行检查,并返回此结果。因此,只有当密钥库中只有一个别名时,此函数才能可靠地工作。对于多个别名,如果
KEY\u alias
位于密钥库中,但未被
alias.nextElement()
作为第一个找到,则会导致误报结果。因此,会为加密和解密创建不同的密钥,这会在解密期间引发AEADBadTagException

如果在
isKeyExists()
中,while循环中的return语句替换为

if (KEY_ALIAS == aliases.nextElement()) return true if(KEY_ALIAS==ALIAS.nextElement())返回true
或者,正如Michael在评论中所建议的那样,如果
isKeyExists(keyStore)
被in
getSymmetricKey()替换,则我无法重现该问题。未修改的代码在我的机器上执行,没有任何问题,尤其是解密工作(安卓P,API级别28以及安卓O,API级别27)。真的吗?这是我的logcat,运行在API 29上,请查看更新版本您确定没有具有给定别名但具有不同属性的旧密钥吗?(旁注:有一个
containsAlias
方法,因此您不必迭代所有别名)。只有当存储中只有一个别名时,
isKeyExists
中的逻辑才能可靠地工作。如果有更多,则在第一次迭代后中止,结果由第一个别名确定。与第一个
return
语句不同,应该有类似于
if(KEY\u ALIAS==ALIAS.nextElement())的内容返回true
。应该是这样的,因为这将生成不同的密钥用于加密和解密,对吗?如果使用Michael的建议,即
isKeyExists(keyStore)
keyStore.containsAlias(密钥别名)
,问题就会自行解决。