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

Python与Java的AES加密结果不一致问题排查求助

Java与Python AES-CBC跨语言加密解密不一致问题排查

我在实现Java和Python应用间的加密通信时,遇到双方解密对方加密字符串结果不一致的问题,排查许久没找到代码问题,求指导。测试用的是32字节消息,相关代码如下:

Java端加密函数

public static String encrypt(String value) {
    try {
        String privateKey = "1234567887654321";
        String stringIV = getRandomIV();
        IvParameterSpec iv = new IvParameterSpec(stringIV.getBytes());
        SecretKeySpec skeySpec = new SecretKeySpec(privateKey.getBytes("UTF-8"), "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

        byte[] encrypted = cipher.doFinal(value.getBytes(StandardCharsets.UTF_8));

        String encryptedString = new String(encrypted);
        String toEncrypt = stringIV + encryptedString;
        return android.util.Base64.encodeToString(toEncrypt.getBytes("UTF-8"), android.util.Base64.DEFAULT);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return null;
}


static String getRandomIV() {
    UUID randomUUID = UUID.randomUUID();
    return randomUUID.toString().replaceAll("_", "").replaceAll("-", "").substring(0,16);
}

Python端解密代码

msg_bytes=bytes(msg, encoding="utf8").decode("utf-8",'ignore')
b64decoded=base64.b64decode(msg_bytes)
cipher = AES.new('1234567887654321'.encode("utf8"), AES.MODE_CBC, b64decoded[0:16])
decoded = cipher.decrypt(b64decoded[16:48])
decoded = bytes(decoded).decode("utf-8",'ignore')

Java端解密函数

public static String decrypt(String encrypted) {
    try {
        String privateKey = "1234567887654321";
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
        byte[] base64decoded = new byte[0];
        base64decoded = android.util.Base64.decode(encrypted, android.util.Base64.DEFAULT);
        String base64decodedString = new String(base64decoded);
        byte[] byteiv = Arrays.copyOfRange(base64decoded, 0, 16);
        IvParameterSpec iv = new IvParameterSpec(byteiv);
        SecretKeySpec skeySpec = new SecretKeySpec(privateKey.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
        byte[] bytes = Hex.decodeHex(hex(base64decodedString.substring(16,48).getBytes()).toCharArray());
        byte[] original = new byte[0];
        byte[] bytemsg = Arrays.copyOfRange(base64decoded, 16, base64decoded.length);
        original = cipher.doFinal(bytemsg);
        return new String(original.toString());
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return null;
}

Python端加密代码

data = str(json.dumps(data))
iv = Random.get_random_bytes(16)
cipher = AES.new('1234567887654321'.encode("utf8"), AES.MODE_CBC, iv)
byte_iv = bytearray(iv)
encrypted = bytearray(cipher.encrypt(self.pad(data).encode("utf8")))
data = base64.b64encode(bytes(byte_iv + encrypted))
data = list(data)
data = bytes(data)

核心问题及修复方案

  1. Java加密时二进制转字符串的编码错误
    加密后的encrypted是二进制字节数组,直接用new String(encrypted)会因二进制数据不符合UTF-8编码规则导致字节丢失或乱码。正确做法是直接拼接IV字节数组和加密字节数组,再做Base64编码:

    // 替换原加密后的字符串拼接逻辑
    byte[] ivBytes = stringIV.getBytes(StandardCharsets.UTF_8);
    byte[] combined = new byte[ivBytes.length + encrypted.length];
    System.arraycopy(ivBytes, 0, combined, 0, ivBytes.length);
    System.arraycopy(encrypted, 0, combined, ivBytes.length, encrypted.length);
    return android.util.Base64.encodeToString(combined, android.util.Base64.DEFAULT);
    
  2. Python解密时硬编码密文长度
    代码中b64decoded[16:48]硬限制了密文长度,只适用于特定测试场景,正确做法是截取16字节IV之后的所有字节作为密文:

    decoded = cipher.decrypt(b64decoded[16:])  # 取IV之后的全部内容作为密文
    
  3. Java解密时字符串转换错误与冗余逻辑

    • new String(original.toString())错误,original.toString()返回的是字节数组的对象标识,而非字节对应的字符串,应改为new String(original, StandardCharsets.UTF_8)
    • 冗余的Hex解码逻辑可直接删除,使用bytemsg即可完成解密
  4. 编码与填充一致性

    • Java解密中privateKey.getBytes()需指定StandardCharsets.UTF_8,避免依赖系统默认编码
    • 确保Python端的pad函数实现PKCS5填充(16字节块大小下,PKCS5与PKCS7填充等价,和Java的PKCS5PADDING匹配)

内容的提问来源于stack exchange,提问作者Shakib Karami

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:09:22