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

使用BouncyCastle解密AES/SIC/PKCS7Padding加密数据时触发BadPaddingException问题排查

问题分析与修复方案

嘿,我一眼就看到你代码里的核心问题了——IV(初始化向量)的处理完全错误,这也是导致BadPaddingException的主要原因!

问题根源

AES/SIC本质是CTR流加密模式,这类模式的核心要求是:解密时必须使用和加密阶段完全相同的IV。而你现在的decrypt方法每次都会调用generateIv()生成一个全新的随机IV,这就导致解密的起始计数器和加密完全对不上,解密出来的字节流完全混乱,PKCS7填充的验证自然会失败,抛出BadPaddingException。

另外还有个小问题:你每次解密都调用Security.addProvider(new BouncyCastleProvider()),重复添加Provider是没必要的,应该只初始化一次。

修复后的代码方案

要解决这个问题,你需要保证解密时使用加密时的原始IV。通常的做法是把IV和密文一起传输(比如拼接在密文前面,再一起Base64编码),解密时先分离出IV再进行解密。以下是完整的修正代码:

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.security.Security;
import java.security.SecureRandom;
import java.util.Base64;

public class AesEncryption {

    // 只初始化一次BouncyCastleProvider,避免重复添加
    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    // 配套的加密方法示例:将IV拼接在密文前16字节后再Base64编码
    public static String encrypt(String aesKey, String plainText) throws Exception {
        SecretKey key = new SecretKeySpec(Base64.getDecoder().decode(aesKey), "AES");
        Cipher cipher = Cipher.getInstance("AES/SIC/PKCS7Padding", "BC");
        
        // 生成加密用的随机IV
        byte[] iv = new byte[16];
        new SecureRandom().nextBytes(iv);
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        
        cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
        byte[] encryptedBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
        
        // 拼接IV和密文:前16字节是IV,后面是实际密文
        byte[] combinedData = new byte[iv.length + encryptedBytes.length];
        System.arraycopy(iv, 0, combinedData, 0, iv.length);
        System.arraycopy(encryptedBytes, 0, combinedData, iv.length, encryptedBytes.length);
        
        return Base64.getEncoder().encodeToString(combinedData);
    }

    public static String decrypt(String aesKey, String cipherText) {
        try {
            SecretKey key = new SecretKeySpec(Base64.getDecoder().decode(aesKey), "AES");
            Cipher dcipher = Cipher.getInstance("AES/SIC/PKCS7Padding", "BC");
            
            // 解码密文,分离出IV和实际加密内容
            byte[] combinedData = Base64.getDecoder().decode(cipherText);
            byte[] iv = new byte[16];
            byte[] encryptedBytes = new byte[combinedData.length - 16];
            
            System.arraycopy(combinedData, 0, iv, 0, iv.length);
            System.arraycopy(combinedData, 16, encryptedBytes, 0, encryptedBytes.length);
            
            // 使用加密时的原始IV初始化解密器
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            dcipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
            
            byte[] decryptedBytes = dcipher.doFinal(encryptedBytes);
            return new String(decryptedBytes, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

关键注意点

  1. 如果加密操作不是你实现的,那你必须从加密方获取加密时使用的原始IV,而不是自己生成——这是解密成功的核心前提。
  2. SIC模式的IV不需要保密,但必须保证唯一性(同一个密钥下不能重复使用同一个IV),所以加密时用随机IV是正确的做法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 18:22:33