C#奇怪输出中的AES加密

时间:2017-06-19 13:33:16

标签: c# encryption cryptography aes

我实现了以下方法:

public static byte[] AESDecrypt(byte[] data, ICryptoTransform transform)
    {
        using (MemoryStream stream = new MemoryStream(data))
        using (CryptoStream cstream = new CryptoStream(stream, transform, CryptoStreamMode.Read))
        using (MemoryStream output = new MemoryStream())
        {
            byte[] buffer = new byte[4000];
            int r;
            while ((r = cstream.Read(buffer, 0, buffer.Length)) > 0)
            {
                output.Write(buffer, 0, r);
            }
            stream.Close();
            return output.ToArray();
        }
    }

我使用此方法解密16字节块的序列,transform参数在开头初始化一次:

AesCryptoServiceProvider provider = new AesCryptoServiceProvider();
provider.Mode = CipherMode.ECB;
provider.KeySize = 128;
provider.BlockSize = 128;
provider.Key = key;
provider.Padding = PaddingMode.PKCS7;
transform = provider.CreateDecryptor();

我的问题是突然该方法开始产生奇怪的输出,16字节块被解密为27字节!!!!,有时16字节被错误地解密为16字节,但是当我重新启动应用程序时,相同的数据产生正确结果,变换是否保持任何使这种情况发生的状态?我做了什么错误,使16字节块解密为27字节。

感谢任何帮助

`编辑:

有人可以确认它是同一个错误: Reuse ICryptoTransform objects

编辑2:

要添加到正确答案的东西:

似乎ICryptoTransform不是线程安全的,所以同时从两个线程调用上面的方法可能会带来麻烦,我通过为使用该方法的每个线程创建ICrypteTransform对象来解决它

1 个答案:

答案 0 :(得分:3)

当您要关闭stream时,您正在关闭cstream

由于您在阅读数据之前不会关闭cstream,因此永远不会调用TransformFinalBlock

最好使用Stream.CopyTo,并使输出流的生命周期比CryptoStream更长。

public static byte[] AESDecrypt(byte[] data, ICryptoTransform transform)
{
    using (MemoryStream output = new MemoryStream())
    {
        using (MemoryStream stream = new MemoryStream(data))
        using (CryptoStream cstream = new CryptoStream(stream, transform, CryptoStreamMode.Read))
        {
            cstream.CopyTo(output);
        }

        return output.ToArray();
    }
}