加密大文件并添加到ZIP

时间:2015-02-12 18:22:43

标签: c# file encryption 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();
}

1 个答案:

答案 0 :(得分:2)

尝试这一点 - 玩块大小以获得性能。我成功地使用了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);
            }
        }
    }
}