You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python与Java AES加解密一致性问题:Java解密报IllegalBlockSizeException

这个问题我之前在做跨语言AES加解密的时候也碰到过,简直踩了好几个坑!javax.crypto.IllegalBlockSizeException这个异常的核心原因很明确:AES作为块加密算法,每个块是16字节,解密时输入的字节数组长度必须是16的倍数(除非用了无填充的流模式)。结合你说的Python解密正常、两边加密结果看似一致的情况,大概率是这几个原因导致的,咱们一个个来捋:

1. Hex编码/解码的不一致(最常见的元凶)

你贴的Java代码片段里的toHexString方法大概率有问题!比如当byte值小于0x10的时候,有没有补前导零?举个例子:如果byte是0x05,要是直接转成Hex字符串是"5"而不是"05",那整个Hex字符串的长度就会比实际需要的短,解码成字节数组时长度自然不是16的倍数,直接触发异常。

Python里的Hex编码通常会把每个byte转成两位十六进制字符,不管值大小,但很多手写的Java Hex方法容易忽略补零的细节。

解决方法:把你的Java Hex转换方法换成标准实现,确保每个byte都转成两位十六进制字符:

// 正确的字节转Hex字符串
private static String toHexString(byte[] data) {
    StringBuilder buf = new StringBuilder();
    for (byte b : data) {
        // 先把byte转成无符号int,再格式化补零
        buf.append(String.format("%02x", b & 0xFF));
    }
    return buf.toString();
}

// 对应的Hex字符串转字节数组
private static byte[] hexStringToByteArray(String hex) {
    int len = hex.length();
    // 先检查长度是否为偶数,避免后续出错
    if (len % 2 != 0) {
        throw new IllegalArgumentException("Hex字符串长度必须为偶数");
    }
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                             + Character.digit(hex.charAt(i+1), 16));
    }
    return data;
}

另外还要注意Hex字符串的大小写,Python可能输出大写,Java解析时如果区分大小写也会出问题,最好统一成小写或大写(上面的代码用的是小写,Python那边也输出小写Hex就好)。

2. 填充模式不匹配

虽然AES的PKCS5Padding和PKCS7Padding在16字节块大小下是等价的,但如果Python端用了NoPadding,而Java端用了默认的PKCS5Padding,就会出问题。因为NoPadding要求明文长度必须是16的倍数,Python可能手动做了填充,但Java解密时会尝试用PKCS5Padding去解,导致长度不匹配。

排查方法:检查Python代码里的AES初始化逻辑,比如用pycryptodome库的话,是不是指定了padding=PKCS7Padding;Java代码里是不是用了Cipher.getInstance("AES/CBC/PKCS5Padding")(或者对应模式)。如果Python用了NoPadding,Java也要同步用NoPadding,并且确保明文、密文长度都是16的倍数。

3. 加密模式或IV的不一致

如果Python用的是CBC模式,Java也必须用CBC模式,并且IV必须完全一致(长度16字节,编码方式相同)。要是Python用了ECB模式(不推荐,安全性差),Java也要对应用ECB模式。模式不一致的话,哪怕加密结果看似一致,解密时也会触发长度异常或者乱码。

排查方法:确认两边的加密模式,比如Python里是不是AES.MODE_CBC,Java是不是"AES/CBC/PKCS5Padding";同时检查IV的生成和传递,比如两边是不是用相同的编码(比如UTF-8)把IV字符串转成字节数组,长度必须是16字节。

4. 密文传递过程中被截断或修改

比如在传递加密后的Hex字符串时,有没有被截断?比如网络传输、存储时丢失了部分字符,导致Hex字符串长度是奇数,解码后字节数组长度就不是整数,更不可能是16的倍数。

排查方法:在Python加密后打印Hex字符串的长度,在Java接收后也打印这个长度,看看是否完全一致。正常情况下,Hex字符串长度应该是偶数,且是32的倍数(因为16字节的AES块转Hex是32字符),多块的话以此类推。

快速验证步骤

  1. 先打印Java解密前的字节数组长度,确认是不是16的倍数;
  2. 用上面的标准Hex方法替换你现有的实现,再测试;
  3. 核对两边的AES模式、填充方式、密钥、IV是否完全一致;
  4. 检查密文在传递过程中有没有被修改。

内容的提问来源于stack exchange,提问作者L..

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:47:40