c# - Zip 然后将多个文件加密到一个存档中

标签 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 需要支持搜索,以便存储可供 Explorer 等应用程序显示其内容的任何位置元数据。此要求不适合我们的用例,因此如果需要,我很乐意解决它。

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

希望有助于阐明我想要实现的目标:

我有多个文件(A、B、C),我想创建一个 zip 存档 (D),然后在同一个 channel (De) 中对其进行加密。所有这些都应该在将 D 存储在磁盘上的情况下完成。我目前正在使用 FileStream 作为测试,它们很可能稍后会成为 MemoryStream,以防止未加密的数据接触文件系统。

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

最佳答案

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

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

文件分为两个主要部分:

<强>1。明文

<强>2。加密

然后将其分为两部分:

2.1。元数据

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

2.2。内容

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

总结

生成的库编写起来相当简单,但是它需要大量的前期思考。话虽这么说,在允许流出存档方面还有一点需要完成。

我希望已经发布了代码,但我目前不方便。如果有人需要帮助完成类似的任务,我将非常乐意提供帮助。

关于c# - Zip 然后将多个文件加密到一个存档中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47576157/

相关文章:

c# - CultureInfo.CurrentCulture 在运行时不会改变

javascript - 如果我将系统日期更改为过去,如何获取当前日期

c# - 加密和解密文本的安全方法?

java - Phpseclib 相当于 Java RSA 加密

c# - 如何以编程方式回滚 EF 7 迁移?

c# - wpf 样式 setter 中的 TemplateBinding?

android - 如何保护 Android 共享首选项?

java - 为什么我的 jar 文件在我的计算机上可以正常工作,但在另一台计算机上却不能?

python - 使用python zipfile查找zip密码

xml - 从 zip 中解码特定的 XML 文件而不提取