Java AES解密返回结果与原明文不一致问题排查修复
问题根因
问题和AES填充逻辑无关,JDK内置的PKCS5Padding填充实现没有问题,不需要调整填充相关逻辑。报错核心原因是方法里Base64编解码的时机完全搞反了,存在两处致命错误:
- 加密分支中,你传入的
info是未编码的原始明文字符串,但代码直接对其做Base64解码。原始明文(比如你传入的"message")不是合法Base64字符串,解码得到的字节是损坏的,后续加密操作处理的根本不是真实明文。 - 解密分支中,
c.doFinal()返回的是原始明文字节数组,但你直接对其做Base64编码后返回,没有把明文字节转成普通UTF-8字符串,返回结果自然和原明文不符。
另外你对密钥的处理逻辑是正确的:SHA-256输出固定32字节,刚好符合AES-256的密钥长度要求,这部分不需要修改。
修复方案
调整两个分支的字节处理逻辑,区分加密、解密场景的编解码规则:
- 加密模式:传入原始明文字符串 → 直接转UTF-8字节数组做加密 → 加密得到的密文字节做Base64编码返回
- 解密模式:传入Base64编码的密文字符串 → 先Base64解码得到密文字节做解密 → 解密得到的明文字节转UTF-8字符串返回
修复后的完整代码如下:
import java.nio.charset.StandardCharsets; import java.util.Base64; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import javax.swing.JOptionPane; static String symmetric(String info, String key, String mode) { try { Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding"); // 密钥处理逻辑保持原有实现即可 byte[] keyBytes = Base64.getDecoder().decode(Crypto.sha256(key)); SecretKeySpec k = new SecretKeySpec(keyBytes, "AES"); if (mode.equals("ENCRYPT")) { c.init(Cipher.ENCRYPT_MODE, k); // 加密场景:原始明文直接转UTF-8字节,不需要Base64解码 byte[] plainBytes = info.getBytes(StandardCharsets.UTF_8); byte[] cipherBytes = c.doFinal(plainBytes); // 密文做Base64编码返回 return Base64.getEncoder().encodeToString(cipherBytes).trim(); } else if (mode.equals("DECRYPT")) { c.init(Cipher.DECRYPT_MODE, k); // 解密场景:传入的是Base64密文,先做Base64解码 byte[] cipherBytes = Base64.getDecoder().decode(info); byte[] plainBytes = c.doFinal(cipherBytes); // 明文字节直接转UTF-8字符串返回,不要做Base64编码 return new String(plainBytes, StandardCharsets.UTF_8).trim(); } } catch (Exception e) { JOptionPane.showMessageDialog(null, e.getMessage()); } return null; }
修复后再执行你之前的加解密调用流程,就能正确得到原始明文"message",不会再出现字符错乱的问题。
内容的提问来源于stack exchange,提问作者Samuel
相关产品推荐
相关产品推荐

