我实现了以下方法:
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对象来解决它
答案 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();
}
}