AES-Encrypt-then-MAC一个大文件与.NET [英] AES-Encrypt-then-MAC a large file with .NET

查看:163
本文介绍了AES-Encrypt-then-MAC一个大文件与.NET的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to encrypt a large file (lets say 64 GB) in the most efficient way in .NET.

我将如何实现:


  1. 创建一个 AesManaged 的实例来加密文件流(读64 GB) li>
  2. 将此流保存到磁盘(因为它是大容纳在内存中)(写64 GB)

  3. 创建一个 HMACSHA512 来计算保存文件的哈希值(读取64 GB)

  4. 使用iv将磁盘保存加密数据(读取和写入64 GB)

  1. Create an instance of AesManaged to encrypt the stream of the file (read 64 GB)
  2. Save this stream to disk (because it is to big to hold in memory) (write 64 GB)
  3. Create an instance of HMACSHA512 to compute hash of the saved file (read 64 GB)
  4. Save encrypted data with iv to disk (read & write 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 。

This implementation has the disadvantage that I created a second file and that I read multiple times 64 GB from disk.

是必需的吗?如何最小化磁盘IO和RAM分配?

Is the necessary? How to minimize disk IO and ram allocation?

推荐答案

我总是得到 CryptoStream 错了,所以请原谅我的伪代码。基本思想是链接流,以便明文被复制到加密的加密中,加密进而将数据写入到执行MACing的密码流,然后将其写入纯文件流:

I always get CryptoStreams wrong, so please excuse my pseudocode. The basic idea is to "chain" streams, so that plaintext gets copied to a cryptostream which does the encryption, which in turn writes data to a cryptostream that does the MACing, which then writes to plain old file stream:

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);

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

This way, you only need a single pass through your 64 Gb.

现在,您必须在加密文件的开始处存储IV和MAC,所以首先调整大小:

Now, you'll have to somehow store the IV and MAC in the beginning of your encrypted file, so first "resize" it:

using(var encryptedFileStream = File.OpenWrite("..."))   
{
    var offset = YourMagicHeaderLength + IvLength + MacLength;
    encryptedFileStream.SetLength(offset);
    encryptedFileStream.Position = offset;

    // The rest of the code goes here
}

然后,在加密和计算MAC之后,回到最初并写出来。

and then, after encrypting and computing MAC, rewind to the very beginning and write them out.

这篇关于AES-Encrypt-then-MAC一个大文件与.NET的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆