AES-Encrypt-then-MAC一个带.NET的大文件

我想在.NET中以最有效的方式加密大文件(比方说64 GB)。

我将如何实现这个:

  1. 创建AesManaged实例以加密文件流(读取64 GB)
  2. 将此流保存到磁盘(因为它在内存中保持较大)(写入64 GB)
  3. 创建HMACSHA512实例以计算保存文件的哈希值(读取64 GB)
  4. 使用iv将加密数据保存到磁盘(读写64 GB)

简化的C#代码:

 using (var aesManaged = new AesManaged()) { using (var msEncrypt = File.OpenWrite(@"C:\Temp\bigfile.bin.tmp")) { using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) { File.OpenRead(@"C:\Temp\bigfile.bin").CopyTo(csEncrypt); new MemoryStream(iv).CopyTo(csEncrypt); } } } using (var hmac = new HMACSHA512(hmacKey)) { hmacHash = hmac.ComputeHash(File.OpenRead(@"C:\Temp\bigfile.bin.tmp")); } byte[] headerBytes; using (var memoryStream = new MemoryStream()) { var header = new Header { IV = iv, HmacHash = hmacHash }; Serializer.Serialize(memoryStream, header); headerBytes = memoryStream.ToArray(); } using (var newfile = File.OpenWrite(@"C:\Temp\bigfile.bin.enc")) { new MemoryStream(MagicBytes).CopyTo(newfile); new MemoryStream(BitConverter.GetBytes(headerBytes.Length)).CopyTo(newfile); new MemoryStream(headerBytes).CopyTo(newfile); File.OpenRead(@"C:\Temp\bigfile.bin.tmp").CopyTo(newfile); } 

这个实现的缺点是我创建了第二个文件 ,并且我从磁盘读取了多次64 GB

有必要吗? 如何最小化磁盘IO和RAM配置?

我总是得到CryptoStream的错误,所以请原谅我的伪代码。 基本思想是“链接”流,以便将明文复制到执行加密的cryptostream,然后将数据写入执行MACing的cryptoverream,然后写入普通的旧文件流:

 using(var encryptedFileStream = File.OpenWrite("...")) using(var macCryptoStream = new CryptoStream(encryptedFileStream, mac, CryptoStreamMode.Write)) using(var encryptCryptoStream = new CryptoStream(macCryptoStream, encryptor, CryptoStreamMode.Write)) using(var inputFileStream = File.OpenRead("...")) inputFileStream.CopyTo(encryptCryptoStream); 

这样,您只需要通过64 Gb一次通过。

现在,您必须以某种方式将IV和MAC存储在加密文件的开头,因此首先“resize”:

 using(var encryptedFileStream = File.OpenWrite("...")) { var offset = YourMagicHeaderLength + IvLength + MacLength; encryptedFileStream.SetLength(offset); encryptedFileStream.Position = offset; // The rest of the code goes here } 

然后,在加密和计算MAC之后,回到最开始并将它们写出来。