AES-Encrypt-then-MAC большой файл с .NET

1

Я хочу зашифровать большой файл (скажем, 64 ГБ) наиболее эффективным способом в.NET.

Как бы это реализовать:

  1. Создайте экземпляр AesManaged для шифрования потока файла (читайте 64 ГБ)
  2. Сохраните этот поток на диск (потому что он большой для хранения в памяти) (напишите 64 ГБ)
  3. Создайте экземпляр HMACSHA512 для вычисления хэша сохраненного файла (прочитайте 64 ГБ)
  4. Сохранение зашифрованных данных с iv на диск (чтение и запись 64 ГБ)

Упрощенный код С#:

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 ГБ с диска.

Это необходимо? Как свести к минимуму дисковое распределение ввода-вывода и вытеснения?

  • 0
    Нет, это не обязательно, если все сделано правильно. Кроме того, шаг 4 является странным, потому что IV должен быть создан перед попыткой шифрования. Обычно записывают IV перед зашифрованным текстом в файл.
Теги:
encryption
hmac
aes

1 ответ

3
Лучший ответ

Я всегда получаю 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 Гб.

Теперь вам нужно как-то сохранить 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, перемотайте с самого начала и запишите их.

  • 0
    Что если я хочу добавить некоторые данные в hmac, но не в результирующий файловый поток?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню