当我尝试在 android 中解密时出现 AES BadTag 异常
AES BadTag Exception when I try to decrypt in android
我正在尝试使用 AES 加密来加密一个简单的字符串。
目前我正在使用 KeyGenerator
生成一个密钥,我正在使用 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
}
}
更新,LOGCAT:
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_ALIAS
。但是,当前的实现仅检查 aliases.nextElement()
找到的 first 别名与 KEY_ALIAS
和 returns 的结果。因此,只有在密钥库中只有一个别名时,此功能才能可靠地工作。如果 KEY_ALIAS
在密钥库中但不是第一个被 aliases.nextElement()
找到,则使用多个别名会导致 假阴性 结果。结果,为加密和解密创建了不同的密钥,这在解密过程中引发了 AEADBadTagException。
将isKeyExists()
中while循环中的return语句换成
即可解决问题
if (KEY_ALIAS == aliases.nextElement()) return true
或者,如 Michael 的评论中所建议,如果 isKeyExists(keyStore)
在 getSymmetricKey()
中被 keyStore.containsAlias(KEY_ALIAS)
替换。
我正在尝试使用 AES 加密来加密一个简单的字符串。
目前我正在使用 KeyGenerator
生成一个密钥,我正在使用 Secure Random
问题是,当我运行这段代码时:
@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
}
}
更新,LOGCAT:
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_ALIAS
。但是,当前的实现仅检查 aliases.nextElement()
找到的 first 别名与 KEY_ALIAS
和 returns 的结果。因此,只有在密钥库中只有一个别名时,此功能才能可靠地工作。如果 KEY_ALIAS
在密钥库中但不是第一个被 aliases.nextElement()
找到,则使用多个别名会导致 假阴性 结果。结果,为加密和解密创建了不同的密钥,这在解密过程中引发了 AEADBadTagException。
将isKeyExists()
中while循环中的return语句换成
if (KEY_ALIAS == aliases.nextElement()) return true
或者,如 Michael 的评论中所建议,如果 isKeyExists(keyStore)
在 getSymmetricKey()
中被 keyStore.containsAlias(KEY_ALIAS)
替换。