简体   繁体   中英

How to Speed Up this Encryption Method C# Filestream

I have encryption method that runs incredible slowly. It takes around 20 minutes to encrypt several hundred MB of data. I'm not sure if I'm taking the right approach. Any help, thoughts, advice would be greatly appreciated.

    private void AES_Encrypt(string inputFile, string outputFile, byte[] passwordBytes, byte[] saltBytes)
    { 
        FileStream fsCrypt = new FileStream(outputFile, FileMode.Create);

        RijndaelManaged AES = new RijndaelManaged();

        AES.KeySize = 256;
        AES.BlockSize = 128;


        var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
        AES.Key = key.GetBytes(AES.KeySize / 8);
        AES.IV = key.GetBytes(AES.BlockSize / 8);
        AES.Padding = PaddingMode.Zeros;

        AES.Mode = CipherMode.CBC;

        CryptoStream cs = new CryptoStream(fsCrypt,
             AES.CreateEncryptor(),
            CryptoStreamMode.Write);

        FileStream fsIn = new FileStream(inputFile, FileMode.Open);

        int data;
        while ((data = fsIn.ReadByte()) != -1)
            cs.WriteByte((byte)data);

        fsCrypt.Flush();
        cs.Flush();
        fsIn.Flush();

        fsIn.Close();
        cs.Close();
        fsCrypt.Close();
}

Thanks for your help!

While encryption can be slow, I wouldn't expect that to be the issue here. I suspect it's the byte-by-byte IO that's causing unnecessary overhead. The simplest way to fix that is with a judicious call to Stream.CopyTo - and while you're at it, you should use using statements to clean up appropriately:

private void AesEncrypt(string inputFile, string outputFile, byte[] passwordBytes, byte[] saltBytes)
{ 
    var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
    RijndaelManaged aes = new RijndaelManaged
    {
        KeySize = 256,
        BlockSize = 128,
        Key = key.GetBytes(AES.KeySize / 8),
        IV = key.GetBytes(AES.BlockSize / 8),
        Padding = PaddingMode.Zeros,
        Mode = CipherMode.CBC
    };

    using (var output = File.Create(outputFile))
    {
        using (var crypto = new CryptoStream(output, aes.CreateEncryptor(), CryptoStreamMode.Write))
        {
            using (var input = File.OpenRead(inputFile))
            {
                input.CopyTo(crypto);
            }
        }
    }
}

As noted on other answers, this isn't a good way of generating an IV. In general I'd prefer to use Rijndael.Create() instead of specifying RijndaelManaged - and you'd probably want to use a using statement for that, too.

You are reading exactly one byte at a time. This generates a lot of overhead.

To speed up your processing, start using more bytes at once or call the internal copy function:

fsIn.CopyTo(cs);

MSDN

Reading one byte at a time is a terrible idea. Use the built in Stream.CopyTo method:

fsIn.CopyTo(cs);

Note also that deriving an IV from the same material that you derive the key from is bad practice and can lead to security vulnerabilities. It can even allow an attacker access to the plaintext in some cases. You should randomly generate an IV for each encryption operation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM