CryptographicException:使用 AesCryptoServiceProvider 加密/解密大文件时“填充无效且无法删除”

问题描述 投票:0回答:1

我正在尝试在 C# 中使用 AES 加密/解密文件。 我的代码可以正常工作,直到我在大文件上尝试它(我正在 4GB 文件上进行测试)。 当我在 4gb 文件上尝试代码时,它会抛出错误 “CryptographicException:填充无效且无法删除。”解密期间。

这是我的代码:

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

}
c# encryption aes
1个回答
0
投票

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

老实说,您不需要任何此代码,您只需使用

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);
© www.soinside.com 2019 - 2024. All rights reserved.