2016-07-27 45 views
0

我想在.NET中以最有效的方式加密大文件(比方說64 GB)。AES-Encrypt-then-MAC與.NET的大文件

我將如何實現這一點:

  1. 創建的AesManaged一個實例文件的流(讀64 GB)加密
  2. 保存此流盤(因爲它是大持有存儲器)(寫64 GB)
  3. 創建的HMACSHA512一個實例計算所保存的文件的哈希值(讀64 GB)
  4. 保存與四到磁盤加密的數據(讀寫& 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分配?

+0

不,這樣做沒有必要做得正確。另外,第4步很奇怪,因爲IV應該在嘗試加密之前創建。通常在文件的密文前寫入IV。 –

回答

2

我總是得到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計算後,快退從一開始就寫出來。

+0

如果我想將一些數據添加到hmac但不是生成的文件流,該怎麼辦? –