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

为何Java AES-ECB-NoPadding不支持非16字节字符串而JavaScript可以?

AES-ECB跨语言加密兼容问题解答

问题1:异常原因分析

CryptoJS的ZeroPadding会自动对不足AES块大小(16字节)的明文补0,直到长度满足16字节的整数倍,因此7字节明文能正常完成加密。而Java的NoPadding要求明文长度必须严格等于块大小的整数倍,7字节不符合该强制要求,所以抛出IllegalBlockSizeException。

问题2:Java代码修改方案

要和JavaScript的加密结果互解,需让Java端实现与CryptoJS完全一致的ZeroPadding逻辑,具体有两种可行方式:

方式1:基于BouncyCastle库实现ZeroPadding

引入BouncyCastle加密库后,直接使用标准的AES/ECB/ZeroPadding模式,示例代码如下:

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;

public class AESZeroPaddingExample {
    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    public static byte[] encrypt(byte[] plainText, byte[] key) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/ZeroPadding", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        return cipher.doFinal(plainText);
    }

    public static byte[] decrypt(byte[] cipherText, byte[] key) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/ZeroPadding", "BC");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        return cipher.doFinal(cipherText);
    }
}

方式2:手动实现ZeroPadding逻辑

若不想引入第三方库,可手动给明文补0至16字节整数倍,解密时再去除末尾的补0:

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class AESManualZeroPadding {
    private static final int BLOCK_SIZE = 16;

    public static byte[] encrypt(byte[] plainText, byte[] key) throws Exception {
        // 计算需要补0的长度
        int paddingLength = BLOCK_SIZE - (plainText.length % BLOCK_SIZE);
        byte[] paddedText = new byte[plainText.length + paddingLength];
        System.arraycopy(plainText, 0, paddedText, 0, plainText.length);
        // 填充0
        for (int i = plainText.length; i < paddedText.length; i++) {
            paddedText[i] = 0;
        }

        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        return cipher.doFinal(paddedText);
    }

    public static byte[] decrypt(byte[] cipherText, byte[] key) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] decrypted = cipher.doFinal(cipherText);
        
        // 去除末尾的补0
        int lastNonZeroIndex = decrypted.length - 1;
        while (lastNonZeroIndex >= 0 && decrypted[lastNonZeroIndex] == 0) {
            lastNonZeroIndex--;
        }
        byte[] result = new byte[lastNonZeroIndex + 1];
        System.arraycopy(decrypted, 0, result, 0, result.length);
        return result;
    }
}

附:相关代码及报错信息

报错的Java示例代码

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class AESNoPaddingError {
    public static void main(String[] args) throws Exception {
        byte[] key = new byte[16]; // 16字节密钥
        byte[] plainText = new byte[7]; // 7字节明文
        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        cipher.doFinal(plainText); // 此处抛出异常
    }
}

无报错的JavaScript示例代码

// 引入CryptoJS库
const CryptoJS = require('crypto-js');

const key = CryptoJS.enc.Hex.parse('00000000000000000000000000000000'); // 16字节密钥
const plainText = CryptoJS.enc.Hex.parse('00000000000000'); // 7字节明文
const cipherText = CryptoJS.AES.encrypt(plainText, key, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.ZeroPadding
});
console.log(cipherText.toString());

报错信息

javax.crypto.IllegalBlockSizeException: Input length not multiple of 16 bytes


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 23:51:11