我正在try 用C#中的AES对文件进行加密/解密. 我的代码一直在运行,直到我在大文件上测试它(我在一个4 GB的文件上测试). 当我在4 GB文件上try 该代码时,它抛出错误 "Cryptograph icException:填充无效,无法删除."在解密过程中.

以下是我的代码:

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

    var aes = new AesCryptoServiceProvider();
    aes.Key = key;
    aes.IV = iv;
    aes.Mode = CipherMode.CBC;
    aes.Padding = PaddingMode.PKCS7;


    using (ICryptoTransform encrypt = aes.CreateEncryptor())
    {
        using (CryptoStream cs = new CryptoStream(fileWriteStream, encrypt, CryptoStreamMode.Write))
        {

            using (fileReadStream)
            {
                var bytesToRead = fileReadStream.Length;
                var chunksToRead = megabyte < fileReadStream.Length ? (int)megabyte : (int)fileReadStream.Length;

                byte[] buffer = new byte[chunksToRead];

                var pos = 0;
                long totalBytesRead = 0;

                fileReadStream.Seek(0, SeekOrigin.Begin);

                int bytesRead = fileReadStream.Read(buffer, 0, chunksToRead);
                var totalBytesReadInChunk = (long)bytesRead;
                while (bytesRead > 0)
                {
                    cs.Write(buffer, 0, chunksToRead);

                    var bytesLeft = fileReadStream.Length - totalBytesReadInChunk;
                    chunksToRead = bytesLeft > megabyte ? megabyte : (int)bytesLeft;

                    bytesRead = fileReadStream.Read(buffer, 0, chunksToRead);
                    totalBytesReadInChunk += bytesRead;
                }
                totalBytesRead += totalBytesReadInChunk;

                cs.FlushFinalBlock();
            }

        }
    }
}


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


    byte[] plainBytes;
    // Instantiate a new Aes object to perform string symmetric encryption
    Aes encryptor = Aes.Create();
    encryptor.Padding = PaddingMode.PKCS7;
    encryptor.Mode = CipherMode.CBC;

    // Set key and IV
    encryptor.IV = iv;

    byte[] aesKey = new byte[32];
    Array.Copy(key, 0, aesKey, 0, 32);
    encryptor.Key = aesKey;


    //// Instantiate a new MemoryStream object to contain the encrypted bytes
    //MemoryStream memoryStream = new MemoryStream();

    // Instantiate a new encryptor from our Aes object
    ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();

    // Instantiate a new CryptoStream object to process the data and write it to the 
    // memory stream
    CryptoStream cryptoStream = new CryptoStream(outputStream, aesDecryptor, CryptoStreamMode.Write);


    var bytesToRead = megabyte < cipherBytes.Length ? (int)megabyte : (int)cipherBytes.Length;

    byte[] buffer = new byte[bytesToRead];

    cipherBytes.Seek(0, SeekOrigin.Begin);
    int bytesRead = cipherBytes.Read(buffer, 0, bytesToRead);
    var totalBytesRead = bytesRead;
    while (bytesRead > 0)
    {
        cryptoStream.Write(buffer, 0, bytesToRead);

        var bytesLeft = cipherBytes.Length - totalBytesRead;
        bytesToRead = bytesLeft > megabyte ? megabyte : (int)bytesLeft;

        bytesRead = cipherBytes.Read(buffer, 0, bytesToRead);
        totalBytesRead += bytesRead;
    }
    cryptoStream.FlushFinalBlock();  //****************ERROR OCCURS HERE

}

推荐答案

您正在写入解密流,而不是读取它.

老实说,你不需要这些代码,你只需使用CopyTo就可以了.

public static void Encrypt(FileStream fileWriteStream,
    FileStream fileReadStream,
    byte[] key,
    byte[] iv)
{
    using var aes = Aes.Create()
    aes.Key = key;
    aes.IV = iv;
    aes.Mode = CipherMode.CBC;
    aes.Padding = PaddingMode.PKCS7;

    using ICryptoTransform encrypt = aes.CreateEncryptor();
    using CryptoStream cs = new CryptoStream(fileWriteStream, encrypt, CryptoStreamMode.Write);
    fileReadStream.CopyTo(cs);
}
public static void Decrypt(
    Stream cipherBytes,
    FileStream outputStream,
    byte[] key,
    byte[] iv)
{
    using var aes = Aes.Create();
    aes.Padding = PaddingMode.PKCS7;
    aes.Mode = CipherMode.CBC;
    aes.IV = iv;
    if (key.Length != 32)
    {
        var aesKey = new byte[32];
        Array.Copy(key, 0, aesKey, 0, 32);
        key = aesKey;
    }
    encryptor.Key = key;

    using ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();
    using CryptoStream cryptoStream = new CryptoStream(cipherBytes, aesDecryptor, CryptoStreamMode.Read);
    cryptoStream.CopyTo(outputStream);
}

也可以考虑使用async个函数.

    await cryptoStream.CopyToAsync(outputStream, someCancellationTokenHere);

Csharp相关问答推荐

旋转时,在另一个对象内按比例zoom 对象

System.Text.Json Utf8JsonReader正在读取数组值两次

访问C#中的数据库字段时获取数据是收件箱错误-为什么?&有效,如果声明不有效

使用变量子根名称在C#中重新初始化SON文件

为什么我不能更改尚未设置的模拟对象属性的值?

需要深入了解NpgSQL DateTimeOffset处理

MudBlazor—MudDataGrid—默认过滤器定义不允许用户修改基本过滤器

发布用于Linux Ubuntu的C#应用程序

为什么在使用动态obj+类obj时会调用串联?

如何使用C#中的主构造函数功能使用多个构造函数?

将字节转换为 struct 并返回

如何将端点(或с匹配请求并判断其路径)添加到BCL?

如何在我的C#应用程序中设置带有reactjs前端的SignalR服务器?

等待一个等待函数

KeyDown从我的文本框中删除输入,如何停止?

多个参数的最小API删除

如何在C#控制台应用程序中获取用户输入并将其作为订单项目进行处理?

删除MudRadio时,MudRadioGroup未 Select 正确的MudRadio

如何在特定时间间隔运行多个后台任务?

处理方法内部过滤与外部过滤