如何加速这种加密方法C#Filestream

时间:2018-01-19 22:15:25

标签: c# encryption filestream

我的加密方法运行速度令人难以置信。加密数百MB的数据大约需要20分钟。我不确定我是否采取了正确的方法。任何帮助,想法,建议将不胜感激。

    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();
}

感谢您的帮助!

3 个答案:

答案 0 :(得分:11)

虽然加密速度很慢,但我不希望这是问题。我怀疑这是逐字节的IO导致不必要的开销。解决问题的最简单方法是明智地调用Stream.CopyTo - 当您处于此状态时,应该使用using语句进行适当的清理:

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);
            }
        }
    }
}

如其他答案所述,这不是产生IV的好方法。一般情况下,我更倾向于使用Rijndael.Create()而不是指定RijndaelManaged - 而且您可能也希望使用using语句。

答案 1 :(得分:6)

您一次只读取一个字节。这会产生很多开销。

要加快处理速度,请立即开始使用更多字节或调用内部复制功能:

fsIn.CopyTo(cs);

MSDN

答案 2 :(得分:2)

一次读取一个字节是个糟糕的主意。使用内置的Stream.CopyTo方法:

fsIn.CopyTo(cs);

另请注意,从您从中获取密钥的相同材料中获取IV是不好的做法,并且可能导致安全漏洞。在某些情况下,它甚至可以允许攻击者访问明文。您应该为每个加密操作随机生成一个IV。