Java使用AES/CBC/PKCS5Padding加解密字符串解密结果为随机乱码
问题原因
AES/CBC模式解密要求必须使用和加密时完全一致的16字节IV(初始化向量),你的代码存在两个核心错误直接导致解密乱码:
- 解密时没有使用加密生成的IV,而是重新调用
new SecureRandom().nextBytes(iv)生成了全新的随机IV,和加密用的IV完全不匹配。 - 加密返回结果仅包含密文的Base64编码,没有把加密时生成的IV一并返回,解密端根本无法获取正确的IV。
你观察到的相同输入每次加密结果不同是正常表现——CBC模式本来就要求每次加密使用不同的随机IV,避免相同明文生成相同密文的安全风险,只要解密时能拿到对应IV就可以正常还原明文。
修复方法
调整加解密逻辑,在加密时把IV和密文拼接后再编码返回,解密时先从解码后的内容中拆分出IV和真实密文,再执行解密操作,不要在解密阶段重新生成IV。
修复后加密代码
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); KeySpec spec = new PBEKeySpec(key.toCharArray(), "salt".getBytes(), 65536, 256); SecretKey secret =new SecretKeySpec(factory.generateSecret(spec).getEncoded(),"AES"); byte[] iv = new byte[16]; new SecureRandom().nextBytes(iv); IvParameterSpec ivp = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secret, ivp); byte[] encryptedText = cipher.doFinal(input.getBytes("UTF-8")); // 拼接IV与密文:固定前16字节为IV,后续字节为真实密文 byte[] combined = new byte[iv.length + encryptedText.length]; System.arraycopy(iv, 0, combined, 0, iv.length); System.arraycopy(encryptedText, 0, combined, iv.length, encryptedText.length); return Base64.getEncoder().encodeToString(combined);
修复后解密代码
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); KeySpec spec = new PBEKeySpec(key.toCharArray(), "salt".getBytes(), 65536, 256); SecretKey secret =new SecretKeySpec(factory.generateSecret(spec).getEncoded(),"AES"); byte[] combined = Base64.getDecoder().decode(input); // 拆分出前16字节作为IV,剩余部分为真实密文 byte[] iv = new byte[16]; byte[] realEncrypted = new byte[combined.length - 16]; System.arraycopy(combined, 0, iv, 0, 16); System.arraycopy(combined, 16, realEncrypted, 0, realEncrypted.length); IvParameterSpec ivp = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, secret, ivp); byte[] decryptedtext = cipher.doFinal(realEncrypted); return new String(decryptedtext, "UTF-8");
注意事项
- IV不需要保密,和密文明文拼接存储/传输不会带来安全风险。
- 代码中硬编码固定salt仅适合本地调试,生产环境建议每次加密使用独立随机salt,和IV、密文一同存储即可。
内容的提问来源于stack exchange,提问作者SOFsomeonenew1015
相关产品推荐
相关产品推荐

