解密文件时抛出javax.crypto.AEADBadTagException问题排查
AEADBadTagException的常见原因 编码/解码逻辑不一致
日志显示的密钥、IV、密文“匹配”可能只是字符串层面的视觉一致,实际字节数组可能存在差异。比如加密时将字节转成Base64存储,解密时却误用Hex解码;或是Base64编码参数(如是否启用URL安全模式、是否保留换行)不一致。务必检查加密和解密环节的字节与字符串互转逻辑,确保两边使用完全相同的编码规则。附加认证数据(AAD)不匹配
GCM模式支持附加认证数据(AAD),若加密时调用了cipher.updateAAD(aadBytes),解密时必须传入完全相同的AAD字节数组——哪怕加密时未传入AAD,解密时也不能额外添加,反之亦然。这是极易被忽略的点,直接影响标签验证结果。密文与认证标签的拆分/拼接错误
GCM的输出通常是「密文 + 认证标签」的组合,若加密后手动拆分了两者,解密时必须将它们准确拼接回完整字节数组再传入cipher.doFinal()。比如默认标签长度为16字节,若拆分时多截或少截了字节,或拼接顺序错误,都会导致标签验证失败。Cipher初始化参数不一致
核对加密和解密时的Cipher初始化细节:- 确保加密用
Cipher.ENCRYPT_MODE、解密用Cipher.DECRYPT_MODE,不可搞反 - 密钥规格必须匹配,比如加密用AES-256密钥,解密时不能按AES-128逻辑处理
- GCM标签长度要统一,比如加密时指定
GCMParameterSpec(128, iv)(128位标签),解密时必须保持相同长度
- 确保加密用
文件读写的字节丢失/篡改
日志中的密文匹配可能仅针对部分数据,实际文件读写时可能因流处理不当导致字节丢失。比如加密时用FileOutputStream写入完整字节,解密时FileInputStream未读取全部内容(如提前关闭流、读取长度计算错误)。可在加密后计算密文的MD5/SHA哈希,解密前先对比哈希值,确认文件密文与加密时完全一致。密钥的实际字节数组不一致
若密钥以字符串形式存储,直接通过new String(keyBytes)和keyString.getBytes()互转可能因字符集问题(如用UTF-8处理非兼容字节)导致密钥字节差异。正确做法是用Base64或Hex编码密钥,避免直接将字节转成字符串。
内容的提问来源于stack exchange,提问作者alex115

