Zip然后将多个文件加密到一个存档

时间:2017-11-30 14:47:07

标签: c# encryption zip compression aes

根据标题我想要获取多个文件,将它们压缩并使用AES256将它们加密到单个存档中。 这可能吗?

我已设法使用以下代码将单个文件转换为单个存档:

internal static void Encrypt(string filePath, string zipPath, byte[] key)
{
    // Create the streams used for encryption.
    using (var outputStream = new FileStream(zipPath, FileMode.Create, FileAccess.Write))
    {
        using (var aes = Aes.Create())
        {
            aes.BlockSize = 128;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;
            aes.KeySize = 256;

            aes.Key = key;
            aes.GenerateIV();

            // Write the IV in to the start of the file first.
            outputStream.Write(aes.IV, 0, aes.IV.Length);

            using (ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
            using (CryptoStream csEncrypt = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write))
            {
                using (DeflateStream zip = new DeflateStream(csEncrypt, CompressionMode.Compress, true))
                {
                    byte[] buffer = new byte[8192];

                    using (var dataStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                    {
                        int bytesRead = dataStream.Read(buffer, 0, buffer.Length);

                        // Read the data in to a buffer to limit memory usage.
                        while (bytesRead > 0)
                        {
                            zip.Write(buffer, 0, bytesRead);

                            bytesRead = dataStream.Read(buffer, 0, buffer.Length);
                        }
                    }
                }

                //Flush after DeflateStream is disposed.
                csEncrypt.FlushFinalBlock();
            }
        }
    }
}

然后我尝试使用ZipArchive进一步使用以下内容来包含多个文件:

internal static void EncryptArchive(string filePath, string zipPath, byte[] key)
{
    // Create the streams used for encryption.
    using (var outputStream = new FileStream(zipPath, FileMode.Create, FileAccess.Write))
    {
        using (var aes = Aes.Create())
        {
            aes.BlockSize = 128;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;
            aes.KeySize = 256;

            aes.Key = key;
            aes.GenerateIV();

            // Write the IV in to the start of the file first.
            outputStream.Write(aes.IV, 0, aes.IV.Length);

            using (ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
            using (CryptoStream csEncrypt = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write))
            {
                using (var zip = new ZipArchive(csEncrypt, ZipArchiveMode.Create, false))
                {
                    byte[] buffer = new byte[8192];

                    var entry = zip.CreateEntry(Path.GetFileName(filePath));

                    using (var dataStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                    using (var entryStream = entry.Open())
                    {
                        int bytesRead = dataStream.Read(buffer, 0, buffer.Length);

                        // Read the data in to a buffer to limit memory usage.
                        while (bytesRead > 0)
                        {
                            entryStream.Write(buffer, 0, bytesRead);

                            bytesRead = dataStream.Read(buffer, 0, buffer.Length);
                        }
                    }
                }

                //Flush after DeflateStream is disposed.
                csEncrypt.FlushFinalBlock();
            }
        }
    }
}

现在虽然该方法没有设置为处理多个文件,但它目前甚至无法处理1.只要我尝试写入 entryStream ,就会抛出一个异常,说明该流不支持CanSeek

我认为ZIP需要支持搜索才能存储可用于资源管理器等应用程序的任何位置元数据以显示其内容。此要求不适合我们的用例,因此如果需要,我很乐意解决它。

我已经查看了其他库但是DotNetZip似乎最近有一些相当糟糕的评论,而不是很多活动。 SharpZipLib确实支持AES 256,但查看源代码它是围绕使用ECB构建的,我们都知道ECB几乎没用。这让我相信我唯一的选择可能是将多个文件写入zip并附带一些元数据,这些元数据可以识别它们在流中的位置(我显然无法找到Seek这些但不是问题。)

希望有助于澄清我想要实现的目标:

我有多个文件(A,B,C),我想创建一个zip存档(D),然后在同一个传递(De)中对其进行加密。所有这一切都应该没有在磁盘上存储D。我目前正在使用FileStream作为测试,以后很可能会MemoryStream以防止未加密的数据触及文件系统。

我错过了什么吗?这可能吗?

1 个答案:

答案 0 :(得分:0)

为了提供答案我实际上已经和@JamesKPolks建议编写我自己的库来进行多个文件的压缩和加密。

我无权提供基于代码的实际解决方案,而且它是根据我们的特定需求量身定制的,因此对其他人来说可能不是最有用的。但总之,采取了以下方法。

该文件分为两个主要部分:

<强> 1。明文

IV

<强> 2。加密

然后将其拆分为两部分:

2.1。元数据

要存储的条目的名称,在末尾填充以帮助基于固定块大小的读取。

2.2。内容

数据条目本身在2.1元数据中以名称条目的哈希标记。内容也以固定块大小写入,并带有填充。

<强>摘要

由此产生的图书馆写起来相当简单,但是它已经预先考虑了很多。话虽如此,仍然有一点点可以完成,允许流式传输存档。

我希望已经发布了这些代码,但目前我并不自由。如果有人需要类似任务的帮助,我会非常乐意提供帮助。