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

BouncyCastle实现AES256 ECB解密报last block incomplete异常

问题背景

在C#环境中使用Bouncy Castle库实现AES 256 ECB模式加解密功能时,加密流程可正常执行并输出密文,但对密文执行解密操作时会抛出异常:Org.BouncyCastle.Crypto.DataLengthException: last block incomplete in decryption,解密流程中断,无法得到正确明文。
涉及的加解密实现代码如下:

public byte[] encrypt(byte[] skey, byte[] data)
{
   PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
   new AesEngine(), new Pkcs7Padding());
   cipher.Init(true, new KeyParameter(skey));
   int outputSize = cipher.GetOutputSize(data.Length);
   byte[] tempOP = new byte[outputSize];
   int processLen = cipher.ProcessBytes(data, 0, data.Length, tempOP, 0);
   int outputLen = cipher.DoFinal(tempOP, processLen);
   byte[] result = new byte[processLen + outputLen];
   Array.Copy(tempOP, 0, result, 0, result.Length);
   return result;
}
public byte[] decrypt(byte[] skey, byte[] data)
{
    PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
    new AesEngine(), new Pkcs7Padding());
    cipher.Init(false, new KeyParameter(skey));
    int outputSize = cipher.GetOutputSize(data.Length);

    byte[] tempOP = new byte[outputSize];
    int processLen = cipher.ProcessBytes(data, 0, data.Length, tempOP, 0);
    int outputLen = cipher.DoFinal(tempOP, processLen);

    byte[] result = new byte[processLen + outputLen];
    Array.Copy(tempOP, 0, result, 0, result.Length);
    return result;    
}
故障原因

给出的加解密核心逻辑本身没有语法错误,触发该异常的核心原因是传入解密方法的密文不符合AES块加密的输入要求,常见场景包括:

  • AES块大小固定为16字节,搭配PKCS7填充时,合法密文的总长度必须是16的整数倍。如果密文在加密输出后、传入解密方法前被截断、篡改,会导致长度不满足要求,触发最后一块不完整的异常。
  • 密文转码错误:这是最高发的诱因。如果加密得到密文字节后,直接使用Encoding.UTF8、Encoding.ASCII等文本编码将密文转为字符串存储/传输,再转回字节数组时,文本编码会将密文中的非法字符序列替换、丢弃,最终得到的字节数组长度不再是16的整数倍,且内容损坏。
  • 密钥不匹配:AES-256要求密钥长度固定为32字节,如果加密和解密使用的密钥字节内容不一致、长度不符合要求,也会在最终块校验阶段抛出该异常。
修复方案
  • 密文转码必须使用二进制安全的Base64编码,禁止直接用文本编码处理密文字节:
    • 加密后转可传输字符串:string cipherStr = Convert.ToBase64String(加密得到的密文字节数组);
    • 解密前从字符串还原密文:byte[] cipherBytes = Convert.FromBase64String(待解密的密文字符串);
  • 在解密方法入口增加密文合法性校验,提前拦截损坏的输入:
public byte[] decrypt(byte[] skey, byte[] data)
{
    // 新增校验逻辑
    if (data == null || data.Length == 0 || data.Length % 16 != 0)
    {
        throw new ArgumentException("密文损坏,长度不符合AES块要求");
    }
    if (skey == null || skey.Length != 32)
    {
        throw new ArgumentException("AES-256密钥长度必须为32字节");
    }

    PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
    new AesEngine(), new Pkcs7Padding());
    cipher.Init(false, new KeyParameter(skey));
    int outputSize = cipher.GetOutputSize(data.Length);

    byte[] tempOP = new byte[outputSize];
    int processLen = cipher.ProcessBytes(data, 0, data.Length, tempOP, 0);
    int outputLen = cipher.DoFinal(tempOP, processLen);

    byte[] result = new byte[processLen + outputLen];
    Array.Copy(tempOP, 0, result, 0, result.Length);
    return result;    
}
  • 校验加解密两端的密钥:确认加密、解密传入的skey字节数组内容完全一致,长度固定为32字节,没有在传递过程中被修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 12:15:34