Java AES加密后Python解密长文本报错问题排查
AES跨语言解密问题排查
问题背景
使用Java代码加密的文本,短内容(如cV6aNGlm3u2sDW+z74y0uA==)可通过Python代码正常解密,但长加密数据解密时抛出UnicodeDecodeError,即使仅解密前16字节也会触发相同错误。
Java加密代码分析
Java端加密核心代码:
public static String encrypt(String value) { Key key = generateKey(); byte[] encValue = new byte[0]; Cipher c; try { c = Cipher.getInstance("AES"); System.out.println(c.getBlockSize()); c.init(Cipher.ENCRYPT_MODE, key); encValue = c.doFinal(value.getBytes()); } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException e) { log.error("Can't encrypt", e); } return Base64.getEncoder().encodeToString(encValue); }
关键细节:
Cipher.getInstance("AES")在Java中默认采用AES/ECB/PKCS5Padding模式(未指定模式和填充时的标准默认实现)value.getBytes()未指定编码,默认使用JVM所在平台的字符编码(如Windows下为GBK,Linux/macOS下为UTF-8)- ECB模式不需要初始化向量(IV)
Python解密代码的问题定位
Python端解密核心代码:
def decrypt_aes(self, encrypted_str): _iv = "\x00" * AES.block_size generator = AES.new(str.encode(self.key), AES.MODE_CBC, self._iv.encode()) encrypted_str_bytes = base64.b64decode(encrypted_str) recovery = generator.decrypt(encrypted_str_bytes) return unpad(recovery, block_size=AES.block_size).decode()
问题根源:
- 加密模式不匹配:Java用ECB模式,Python却用CBC模式——这是解密乱码的核心原因。ECB和CBC是完全不同的分组加密模式,即使IV设为全0,也无法正确解密ECB加密的数据。
- 编码潜在不兼容:Java端
value.getBytes()的默认编码可能与Python端decode()(默认UTF-8)不一致,短文本(如纯英文)因编码兼容无报错,长文本包含多字节字符时就会触发解码错误。 - 填充逻辑隐性冲突:Java默认PKCS5Padding,若Python的
unpad函数不是标准PKCS5实现,会导致解密后内容损坏。
修复方案
修改Python解密代码,完全对齐Java端的加密逻辑:
from Crypto.Cipher import AES from Crypto.Util.Padding import unpad import base64 def decrypt_aes(self, encrypted_str): # 切换为ECB模式,无需IV generator = AES.new(str.encode(self.key), AES.MODE_ECB) encrypted_str_bytes = base64.b64decode(encrypted_str) recovery = generator.decrypt(encrypted_str_bytes) # 使用标准PKCS5填充的unpad实现 decrypted_bytes = unpad(recovery, block_size=AES.block_size) # 对齐Java端的默认编码:若Java用GBK则改为'gbk',否则用'utf-8' return decrypted_bytes.decode('utf-8')
额外注意:
- 确认Java端
generateKey()生成的密钥长度与Python端一致(AES密钥长度为16/24/32字节,对应AES-128/192/256) - 若Java端明确指定了编码(如
value.getBytes(StandardCharsets.UTF_8)),Python端解码时需保持完全一致
内容的提问来源于stack exchange,提问作者Nikita
相关产品推荐
相关产品推荐

