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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Zip然后将多个文件加密到单个存档中相关的知识,希望对你有一定的参考价值。

根据标题我想要获取多个文件,将它们压缩并使用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需要支持搜索,以便存储可用于Explorer等应用程序的任何位置元数据以显示其内容。此要求不适合我们的用例,因此如果需要,我很乐意解决它。

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

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

我有多个文件(A,B,C),我想创建一个zip存档(D),然后在同一个传递(De)中加密它。所有这一切都应该在不存储D的情况下完成。我目前正在使用FileStreams作为测试,很可能以后这些将是MemoryStreams以防止未加密的数据触及文件系统。

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

答案

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

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

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

1.明文

IV

2.加密

然后将其分为两部分:

2.1。元数据

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

2.2。内容

数据条目本身在开始时由2.1元数据中的名称条目的哈希标记。内容也以填充的固定块大小写入。

摘要

由此产生的库在编写时相当简单,但它已经预先考虑了相当多的想法。话虽如此,仍有一点点可以完成,允许流式传输出档案。

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

以上是关于Zip然后将多个文件加密到单个存档中的主要内容,如果未能解决你的问题,请参考以下文章

使用 7zip 命令行实用程序解密加密的 7zip 存档文件

将 zip 存档拆分为多个块

从 zip 存档中提取单个文件

使用 Minizip API 从 Zip 存档中删除 Zip 条目

在 ftp_get() 使用 PHP 的 ZIP 文件之前,在 FTP 服务器上以 ZIP 格式存档文件

缓存存档文件的最佳方法是啥?