使用 MemoryStream 时 AES 解密结果不正确
为什么这段代码不起作用?可能我做错了什么,但我找不到什么。
当我运行下面的代码时,我看到消息的唯一部分被正确解密。据我了解,由于某种原因 cryptoStreamReader.ReadToEnd()
不会读取整个文件。
实际上,我已经通过使用 XmlTextReader 和 StringReader 进行加密/解密而不是 MemoryStream 解决了该任务。但我想知道该代码有什么问题。有人可以帮我找出来吗?先感谢您!
-
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Collections.Generic;
namespace Tests
{
internal static class Program
{
private static void Main()
{
#if GENERATE_DATA
var list = new List<int>();
for (int i = 0; i <= 5 * 1024; i++)
list.Add(i);
using (var fileStream = new FileStream("data.xml", FileMode.Create))
{
var serializer = new DataContractSerializer(list.GetType());
serializer.WriteObject(fileStream, list);
}
#endif
var originalData = GetData<List<int>>();
SerializeAndEncrypt(originalData);
var restoredData = DecryptAndDeserialize<List<int>>();
Console.ReadKey();
}
private static T GetData<T>()
{
using (var fileStream = new FileStream("data.xml", FileMode.Open))
{
var serializer = new DataContractSerializer(typeof(T));
return (T)serializer.ReadObject(fileStream);
}
}
private const string ENCRYPTED_DATA_FILE_NAME = "data.enc";
// 32 bytes
private static readonly byte[] KEY = new byte[]
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2
};
// 16 bytes
private static readonly byte[] INITIALIZATION_VECTOR = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 };
private static string _toEncrypt;
private static string _decrypted;
private static void SerializeAndEncrypt<T>(T data)
{
var memoryStream = new MemoryStream();
var serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(memoryStream, data);
memoryStream.Position = 0L;
var memoryStreamReader = new StreamReader(memoryStream);
var fileStream = File.Open(ENCRYPTED_DATA_FILE_NAME, FileMode.Create);
var aes = Aes.Create();
var cryptoTransform = aes.CreateEncryptor(KEY, INITIALIZATION_VECTOR);
var cryptoStream = new CryptoStream(fileStream, cryptoTransform, CryptoStreamMode.Write);
var cryptoStreamWriter = new StreamWriter(cryptoStream);
_toEncrypt = memoryStreamReader.ReadToEnd();
cryptoStreamWriter.Write(_toEncrypt);
cryptoStream.Close();
fileStream.Close();
memoryStream.Close();
}
private static T DecryptAndDeserialize<T>()
{
var fileStream = File.Open(ENCRYPTED_DATA_FILE_NAME, FileMode.Open);
var aes = Aes.Create();
var cryptoTransform = aes.CreateDecryptor(KEY, INITIALIZATION_VECTOR);
var cryptoStream = new CryptoStream(fileStream, cryptoTransform, CryptoStreamMode.Read);
var cryptoStreamReader = new StreamReader(cryptoStream);
var memoryStream = new MemoryStream();
var memoryStreamWriter = new StreamWriter(memoryStream);
// The following line is shorter than the original (_toEncrypt). Why? :(
_decrypted = cryptoStreamReader.ReadToEnd();
memoryStreamWriter.Write(_decrypted);
memoryStream.Position = 0L;
var serializer = new DataContractSerializer(typeof(T));
var result = (T)serializer.ReadObject(memoryStream);
memoryStream.Close();
cryptoStream.Close();
fileStream.Close();
return result;
}
}
}
-
Why doesn't this code work? Probably I've done somethig wrong, but I can't find what.
When I run the code below I see that the only a part of message is correctly decrypted. As I understand, the cryptoStreamReader.ReadToEnd()
doesn't read the whole file for some reason.
Actually I've solved the task by using XmlTextReader and StringReader for encryption/decryption instead of MemoryStream. But I want to know what's wrong with that code. Could anyone help me please to find it out? Thank you in advance!
-
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Security.Cryptography;
using System.Collections.Generic;
namespace Tests
{
internal static class Program
{
private static void Main()
{
#if GENERATE_DATA
var list = new List<int>();
for (int i = 0; i <= 5 * 1024; i++)
list.Add(i);
using (var fileStream = new FileStream("data.xml", FileMode.Create))
{
var serializer = new DataContractSerializer(list.GetType());
serializer.WriteObject(fileStream, list);
}
#endif
var originalData = GetData<List<int>>();
SerializeAndEncrypt(originalData);
var restoredData = DecryptAndDeserialize<List<int>>();
Console.ReadKey();
}
private static T GetData<T>()
{
using (var fileStream = new FileStream("data.xml", FileMode.Open))
{
var serializer = new DataContractSerializer(typeof(T));
return (T)serializer.ReadObject(fileStream);
}
}
private const string ENCRYPTED_DATA_FILE_NAME = "data.enc";
// 32 bytes
private static readonly byte[] KEY = new byte[]
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 0,
1, 2
};
// 16 bytes
private static readonly byte[] INITIALIZATION_VECTOR = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6 };
private static string _toEncrypt;
private static string _decrypted;
private static void SerializeAndEncrypt<T>(T data)
{
var memoryStream = new MemoryStream();
var serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(memoryStream, data);
memoryStream.Position = 0L;
var memoryStreamReader = new StreamReader(memoryStream);
var fileStream = File.Open(ENCRYPTED_DATA_FILE_NAME, FileMode.Create);
var aes = Aes.Create();
var cryptoTransform = aes.CreateEncryptor(KEY, INITIALIZATION_VECTOR);
var cryptoStream = new CryptoStream(fileStream, cryptoTransform, CryptoStreamMode.Write);
var cryptoStreamWriter = new StreamWriter(cryptoStream);
_toEncrypt = memoryStreamReader.ReadToEnd();
cryptoStreamWriter.Write(_toEncrypt);
cryptoStream.Close();
fileStream.Close();
memoryStream.Close();
}
private static T DecryptAndDeserialize<T>()
{
var fileStream = File.Open(ENCRYPTED_DATA_FILE_NAME, FileMode.Open);
var aes = Aes.Create();
var cryptoTransform = aes.CreateDecryptor(KEY, INITIALIZATION_VECTOR);
var cryptoStream = new CryptoStream(fileStream, cryptoTransform, CryptoStreamMode.Read);
var cryptoStreamReader = new StreamReader(cryptoStream);
var memoryStream = new MemoryStream();
var memoryStreamWriter = new StreamWriter(memoryStream);
// The following line is shorter than the original (_toEncrypt). Why? :(
_decrypted = cryptoStreamReader.ReadToEnd();
memoryStreamWriter.Write(_decrypted);
memoryStream.Position = 0L;
var serializer = new DataContractSerializer(typeof(T));
var result = (T)serializer.ReadObject(memoryStream);
memoryStream.Close();
cryptoStream.Close();
fileStream.Close();
return result;
}
}
}
-
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您必须刷新您的 StreamWriter 才能将缓冲数据写入底层
设备:
希望这有帮助。
You have to flush your
StreamWriter
in order to get buffered data written to the underlyingdevice:
Hope, this helps.