【问题标题】:Add cleartext bytes to the beginning of a CryptoStream?将明文字节添加到 CryptoStream 的开头?
【发布时间】:2015-08-30 23:16:44
【问题描述】:

我有一个这样定义的接口:

public interface IEncryptionService
{
    Stream Encrypt(Stream cleartext);
    Stream Decrypt(Stream encrypted);
}

我正在使用AesCryptoServiceProvider 实现这个接口,但这里显然存在问题。 IV(初始化向量)没有在界面上返回......所以加密一些东西可以正常工作,只要我不想再次解密它。 Decrypt() 方法根本没有机会工作。

我想要做的是在流的开头以明文形式包含 IV,然后将 CryptoStream 添加到其中,因此它本质上是带有“标题”的加密数据,我可以将其剥离并用于解密流。

那么...我该怎么做呢?我可以很容易地创建 CryptoStream,但看起来这会加密 IV,这有点违背了目的。我可以将CryptoStream 加载到内存中,预先添加IV,然后将其作为MemoryStream 流式传输,但这确实效率低下,并且会在大流上死掉。

对此有什么好的、安全的、可扩展的做法?

【问题讨论】:

  • 您的 CryptoStream 可能已经有一个 MemoryStream 作为后备存储。制作一个 IV 数组并将其直接写入该 MemoryStream ,然后将纯文本写入您的 CryptoStream 。我相信这就是我过去的做法。
  • @WDS,你能举个例子吗?
  • 是的,需要几分钟,但我会的。

标签: c# encryption stream cryptostream


【解决方案1】:

这就是我的想法。看看你如何将 IV 写入 MemoryStream,然后使用加密货币跟随它?然后当你想解密时,用同样的方法先把IV拉下来。

对不起,久违了。这个正在工作。如果您不强制转换 ms toArray(); 它应该可以很好地扩展。在最后。例如,随时写入 FileStream,您根本不需要太多内存。这只是为了演示在 IV 之前。

    private byte[] encrypt(byte[] originalPlaintextBytes)
    {
        using (SymmetricAlgorithm algorithm = AesCryptoServiceProvider.Create())
        {
            algorithm.GenerateKey();
            algorithm.GenerateIV();
            byte[] iv = algorithm.IV;
            byte[] key = algorithm.Key;
            using (ICryptoTransform encryptor = algorithm.CreateEncryptor(key, iv))
            {
                using (MemoryStream ms = new MemoryStream())
                using (CryptoStream cs = new CryptoStream(ms, encryptor,CryptoStreamMode.Write))
                {
                    BinaryWriter bw = new BinaryWriter(ms);
                    bw.Write(iv);
                    cs.Write(originalPlaintextBytes, 0, originalPlaintextBytes.Length);
                    return ms.ToArray();
                }
            }
        }
    }

好吧,不用编辑上面的代码,这里是一个随机创建一个1兆字节的明文文件的完整程序。然后将其加密为密文。请注意,该程序永远不需要 1 兆字节的内存来运行。它是完全可扩展的。同样,和以前一样,这个程序是为了演示这个概念,如果 readBuffer 大于 1 字节,你会做得更好。但我不想创造它并掩盖核心答案。我希望这有帮助。我认为这正是您需要的那种方法。

using System;
using System.IO;
using System.Security.Cryptography;
using System.Windows.Forms;

namespace SO_AES
{
    public partial class Form1 : Form
    {
        Random ran = new Random();
        public Form1()
        {
            InitializeComponent();
            using (var file = File.Open("Plaintext.txt", FileMode.OpenOrCreate))
            {
                byte[] junkBytes = new byte[1000];
                for (int i = 0; i < 1000; i++)
                {
                    for (int j = 0; j < 1000; j++)
                    {
                        junkBytes[j] = (byte)ran.Next(0, 255);
                    }
                    file.Write(junkBytes, 0, junkBytes.Length);
                }
            }

            using (var plainTextFile = File.Open("Plaintext.txt", FileMode.Open))
            {
                using (var cryptoTextFile = File.Open("Crypto.txt", FileMode.OpenOrCreate))
                {
                    encrypt(plainTextFile, cryptoTextFile);
                }
            }
        }

        void encrypt(Stream inStream, Stream outStream)
        {
            using (SymmetricAlgorithm algorithm = AesCryptoServiceProvider.Create())
            {
                algorithm.GenerateKey();
                algorithm.GenerateIV();
                byte[] iv = algorithm.IV;
                byte[] key = algorithm.Key;
                using (ICryptoTransform encryptor = algorithm.CreateEncryptor(key, iv))
                {
                    using (CryptoStream cs = new CryptoStream(outStream, encryptor, CryptoStreamMode.Write))
                    {
                        BinaryWriter bw = new BinaryWriter(outStream);
                        bw.Write(iv);
                        byte[] readBuffer = new byte[1];
                        BinaryReader br = new BinaryReader(inStream);
                        while (br.Read(readBuffer, 0, readBuffer.Length) != 0)
                        {
                            cs.Write(readBuffer, 0, 1);
                        }
                    }
                }
            }
            inStream.Close();
            outStream.Close();
        }
    }
}

【讨论】:

  • 嗯。这将如何扩展?看起来您首先将所有内容加载到内存中。
  • 呃,我这里搞错了。让我检查问题并进行编辑。正如它所发布的那样,MemoryStream 没有保留 IV。
  • 您应该能够用 FileStream 代替 MemoryStream 并且几乎不使用内存来运行它,无论您的纯文本有多大。
  • 哦,是的,如果您希望它像那样缩放,您还需要修改此方法以接受 Stream 作为参数而不是数组。很容易做到。我的主要目标是在 IV 之前进行演示。
  • 这...看起来可能会起作用。我会试一试,然后回复你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-31
  • 2021-06-28
  • 2011-08-30
  • 2021-11-14
  • 1970-01-01
  • 2015-09-07
相关资源
最近更新 更多