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

使用AesCryptoServiceProvider加密解密大文件时出现填充无效异常

问题分析与修复方案

核心问题

你的代码在处理4GB大文件时抛出Padding is invalid and cannot be removed异常,根源在于加密、解密阶段都错误地写入了固定长度的缓冲区数据,而非实际读取到的字节数,导致加密后的文件混入无效残留数据,解密时无法通过PKCS7填充验证。

具体错误点

  • 加密方法的写入错误:循环中每次读取到bytesRead字节后,调用cs.Write(buffer, 0, chunksToRead),但chunksToRead是预设的块大小,最后一次读取大概率不足该值,此时会把缓冲区中之前的残留数据写入加密流,破坏加密文件的完整性。
  • 解密方法的写入错误:同样的逻辑问题,读取到bytesRead字节后,却写入bytesToRead长度的数据,导致解密时处理了多余的无效数据,触发填充验证失败。
  • Key处理不一致:加密方法直接使用传入的key,解密方法却强制复制32字节生成aesKey,若原key长度非32字节,会导致加解密密钥不一致,也可能引发异常。

修复后的代码

加密方法

public static void Encrypt(FileStream fileWriteStream,
    FileStream fileReadStream,
    byte[] key,
    byte[] iv)
{
    const int megabyte = 1024 * 1024;

    using var aes = Aes.Create();
    aes.Key = key;
    aes.IV = iv;
    aes.Mode = CipherMode.CBC;
    aes.Padding = PaddingMode.PKCS7;

    using var encrypt = aes.CreateEncryptor();
    using var cs = new CryptoStream(fileWriteStream, encrypt, CryptoStreamMode.Write);
    
    fileReadStream.Seek(0, SeekOrigin.Begin);
    byte[] buffer = new byte[megabyte];
    int bytesRead;
    while ((bytesRead = fileReadStream.Read(buffer, 0, buffer.Length)) > 0)
    {
        cs.Write(buffer, 0, bytesRead); // 仅写入实际读取到的有效字节
    }
    cs.FlushFinalBlock();
}

解密方法

public static void DecryptToBytes(Stream cipherBytes,
    FileStream outputStream,
    byte[] key,
    byte[] iv)
{
    const int megabyte = 1024 * 1024;

    using var encryptor = Aes.Create();
    encryptor.Padding = PaddingMode.PKCS7;
    encryptor.Mode = CipherMode.CBC;
    encryptor.IV = iv;
    encryptor.Key = key; // 保持与加密一致的密钥处理逻辑

    using var aesDecryptor = encryptor.CreateDecryptor();
    using var cryptoStream = new CryptoStream(outputStream, aesDecryptor, CryptoStreamMode.Write);
    
    cipherBytes.Seek(0, SeekOrigin.Begin);
    byte[] buffer = new byte[megabyte];
    int bytesRead;
    while ((bytesRead = cipherBytes.Read(buffer, 0, buffer.Length)) > 0)
    {
        cryptoStream.Write(buffer, 0, bytesRead); // 仅写入实际读取到的有效字节
    }
    cryptoStream.FlushFinalBlock();
}

关键优化说明

  • 简化循环逻辑,移除冗余的长度计算变量,直接用缓冲区长度作为每次读取的最大值,避免块大小计算错误。
  • 严格以实际读取的bytesRead值写入加密/解密流,确保只处理有效数据。
  • 统一加解密的密钥处理逻辑,避免密钥不一致问题。
  • 使用using var语法(C# 8.0+)简化资源管理,确保所有流和加密对象自动正确释放。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 04:42:03