AES加密然后用MAC访问一个大文件.NET

本文关键字:一个 NET 文件 然后 加密 MAC 访问 AES | 更新日期: 2023-09-27 17:59:08

我想用中最有效的方式加密一个大文件(比如说64GB)。NET。

我将如何实现:

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

简化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);
}

此实现具有的缺点,即我创建了第二个文件并且我。

有必要吗?如何最大限度地减少磁盘IO和内存分配?

AES加密然后用MAC访问一个大文件.NET

我总是弄错CryptoStream,所以请原谅我的伪代码。基本思想是"链接"流,这样明文就被复制到进行加密的加密流中,加密流又将数据写入进行MACing的加密流,然后写入普通的旧文件流:

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存储在加密文件的开头,所以首先"调整"它的大小:

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

然后,在加密和计算MAC后,倒带到最开始并把它们写出来。