使用 MemoryStream 时 AES 解密结果不正确

发布于 2024-12-13 18:23:58 字数 4269 浏览 1 评论 0原文

为什么这段代码不起作用?可能我做错了什么,但我找不到什么。

当我运行下面的代码时,我看到消息的唯一部分被正确解密。据我了解,由于某种原因 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

痴情换悲伤 2024-12-20 18:23:58

您必须刷新您的 StreamWriter 才能将缓冲数据写入底层
设备:

private static void SerializeAndEncrypt<T>(T data)
{                
  ...

  _toEncrypt = memoryStreamReader.ReadToEnd();
  cryptoStreamWriter.Write(_toEncrypt);

  // Flush your stream writer. So all buffered
  // data get written to the underlying device.
  cryptoStreamWriter.Flush(); 

  cryptoStream.Close();
  fileStream.Close();
  memoryStream.Close();
}

private static T DecryptAndDeserialize<T>()
{
  ...

  _decrypted = cryptoStreamReader.ReadToEnd();
  memoryStreamWriter.Write(_decrypted);

  // Flush buffered data.
  memoryStreamWriter.Flush();

  memoryStream.Position = 0L;
  var serializer = new DataContractSerializer(typeof(T));
  var result = (T)serializer.ReadObject(memoryStream);
  memoryStream.Close();
  cryptoStream.Close();
  fileStream.Close();

  return result;
}

希望这有帮助。

You have to flush your StreamWriter in order to get buffered data written to the underlying
device:

private static void SerializeAndEncrypt<T>(T data)
{                
  ...

  _toEncrypt = memoryStreamReader.ReadToEnd();
  cryptoStreamWriter.Write(_toEncrypt);

  // Flush your stream writer. So all buffered
  // data get written to the underlying device.
  cryptoStreamWriter.Flush(); 

  cryptoStream.Close();
  fileStream.Close();
  memoryStream.Close();
}

private static T DecryptAndDeserialize<T>()
{
  ...

  _decrypted = cryptoStreamReader.ReadToEnd();
  memoryStreamWriter.Write(_decrypted);

  // Flush buffered data.
  memoryStreamWriter.Flush();

  memoryStream.Position = 0L;
  var serializer = new DataContractSerializer(typeof(T));
  var result = (T)serializer.ReadObject(memoryStream);
  memoryStream.Close();
  cryptoStream.Close();
  fileStream.Close();

  return result;
}

Hope, this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文