2016-07-27 3 views
0

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

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

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

Упрощенная 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 Гб с диска.

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

+0

Нет, это не обязательно, когда сделано правильно. Кроме того, шаг 4 является странным, потому что IV должен быть создан, прежде чем пытаться зашифровать. Обычно записывать IV перед зашифрованным текстом в файл. –

ответ

2

Я всегда получаю CryptoStream s неправильно, поэтому, пожалуйста, извините мой псевдокод. Основная идея заключается в «цепочке» потоков, так что открытый текст копируется в криптостол, который выполняет шифрование, которое, в свою очередь, записывает данные в криптооптим, который выполняет 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, но не в результирующий поток? –

Смежные вопросы