簡體   English   中英

加密大文件並添加到ZIP

[英]Encrypt large file and add to ZIP

我的目標是加密大型(cca 10 GB)輸入文件,並將其附加到現有的System.IO.Packaging包中。 我只能使用.NET Framework 3.5,不能使用任何第三方庫。

我嘗試了十種方法,但均未成功。 我試圖將輸入讀取到Stream,對其進行加密並保存到PackagePart。 我試圖逐字節讀取輸入文件,然后對讀取的字節進行加密並將其也從PackagePart追加到Stream。 每次我發現一個新問題時(例如CryptoStream不支持查找等)。

你能告訴我正確的方法嗎?

//method to create zip file (just a sample)
public static void AppendToZip(SomeType encryptedData)
{
   using (Package zip = Package.Open(@"C:\myarchive.zip", FileMode.OpenOrCreate))
   {
      Uri uri = PackUriHelper.CreatePartUri(new Uri("/files/test.enc", UriKind.Relative));

      try
      {
    part = zip.GetPart(uri);
      }
      catch
      {
      }

      if (part == null)
      {
         part = zip.CreatePart(uri, "", CompressionOption.Maximum);
      }

      using (Stream dest = part.GetStream())
      {
         //how to write encryptedData to destination stream?
      }
   }
}

//sample method for encrypting a file
private static void Encrypt(string inputFile, string cryptFile, byte[] passwordBytes, byte[] saltBytes)
{
   FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);

   RijndaelManaged AES = new RijndaelManaged();

   AES.KeySize = 256;
   AES.BlockSize = 128;


   var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
   AES.Key = key.GetBytes(AES.KeySize / 8);
   AES.IV = key.GetBytes(AES.BlockSize / 8);
   AES.Padding = PaddingMode.Zeros;

   AES.Mode = CipherMode.CBC;

   CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write);

   FileStream fsIn = new FileStream(inputFile, FileMode.Open);

   int data;
   while ((data = fsIn.ReadByte()) != -1)
   {
      cs.WriteByte((byte)data);
   }

   fsIn.Close();
   cs.Close();
   fsCrypt.Close();
}

試試看-試玩塊大小以提高性能。 我使用3.5 GB ISO成功完成了此操作。 但是,zip文件壓縮壓縮的內容要大得多,因此正如另一個人所說,最好先壓縮文件,然后再對其進行加密。 但是我不知道您的要求,所以這是。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO.Packaging;

namespace ZipTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // Block size we apply to all reads / writes
            const int BLOCK_SIZE = 65536;

            // The zip file we're using
            var zipFileName = @"C:\temp\ZipSO\MyZip.zip";

            // Password for encryption
            var password = "ThisIsMyPassword";

            // Name of temp file where we'll encrypt the file first
            var intermediateFile = @"C:\temp\ZipSO\Intermediate_" + Guid.NewGuid().ToString();

            // File we're encrypting / adding to archive
            var inputFile = @"C:\temp\ZipSO\InputFile.txt";

            // Salt for encryption
            var salt = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

            // For the new / existing package part
            PackagePart part = null;

            // Open the archive
            using (var zip = Package.Open(zipFileName, System.IO.FileMode.OpenOrCreate))
            {
                // Uri for the part
                var uri = PackUriHelper.CreatePartUri(new Uri("/files/test.enc", UriKind.Relative));

                // Get existing part if found, or create new
                if (zip.PartExists(uri))
                    part = zip.GetPart(uri);
                else
                    part = zip.CreatePart(uri, "", CompressionOption.Maximum);

                // Encrypt the file first
                var passBytes = System.Text.Encoding.ASCII.GetBytes(password);
                using (var fs = new System.IO.FileStream(intermediateFile, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write))
                {
                    var key = new System.Security.Cryptography.Rfc2898DeriveBytes(passBytes, salt, 1000);
                    var keySize = 256;
                    var blockSize = 128;

                    var aes = new System.Security.Cryptography.RijndaelManaged()
                    {
                        KeySize = keySize,
                        BlockSize = blockSize,
                        Key = key.GetBytes(keySize / 8),
                        IV = key.GetBytes(blockSize / 8),
                        Padding = System.Security.Cryptography.PaddingMode.Zeros,
                        Mode = System.Security.Cryptography.CipherMode.CBC
                    };

                    using (var fsSource = new System.IO.FileStream(inputFile, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                    {
                        using (var cs = new System.Security.Cryptography.CryptoStream(fs, aes.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write))
                        {
                            var readBytes = new byte[BLOCK_SIZE];
                            int read;
                            while ((read = fsSource.Read(readBytes, 0, BLOCK_SIZE)) != 0)
                            {
                                cs.Write(readBytes, 0, read);
                            }
                            cs.Close();
                        }
                        fsSource.Close();
                    }
                    fs.Close();
                }

                // Now add it to the archive
                using (var p = part.GetStream(System.IO.FileMode.OpenOrCreate))
                {
                    using (var source = new System.IO.FileStream(intermediateFile, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                    using (var bw = new System.IO.BinaryWriter(p))
                    {
                        var readBytes = new byte[BLOCK_SIZE];
                        int read;
                        while ((read = source.Read(readBytes, 0, BLOCK_SIZE)) != 0)
                        {
                            bw.Write(readBytes.Take(read).ToArray());
                        }
                    }
                }

                // Clean up the intermediate
                System.IO.File.Delete(intermediateFile);
            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM