【问题标题】:Encrypt an existing zip file加密现有的 zip 文件
【发布时间】:2012-10-09 07:35:33
【问题描述】:

我有一个现有的 zip 文件,我想使用 AESManaged 类对其进行加密,但我找不到在哪里可以为该类中的 zip 文件设置密码。经过研究,我发现一些诸如“DotNetZip”之类的库可以完成任务。但是我的文件已经是.zip,我不需要再次压缩,我只想加密它。任何人都可以帮助我使用 AESManaged 类来实现目的吗?

谢谢

【问题讨论】:

  • AesManaged 与文件内容无关,所以不管你的文件内容是什么(zip 或普通文件)。如果你想加密 zip 文件的内容(不是 zip 文件本身),你应该先解压文件,然后将解压后的内容发送到AesManaged class。
  • @MD.Unicorn 感谢您的快速回复,如果我想加密zip文件本身,而不是内容,所以当我解压缩时,我需要输入密码,我应该使用什么类?

标签: c# encryption zip


【解决方案1】:

我不知道这是否是您正在寻找的,但我创建了一个加密任何文件的代码。

这是加密器的代码:

private void EncryptFile(string inputFile, string outputFile)
        {
            string password = @"yourPWhere";
            UnicodeEncoding UE = new UnicodeEncoding();
            byte[] key = CreateKey(password);

            string cryptFile = outputFile;
            FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);

            RijndaelManaged RMCrypto = new RijndaelManaged();
            IV = CreateIV(password_mTxtBx.Text);

            CryptoStream cs = new CryptoStream(fsCrypt,
                RMCrypto.CreateEncryptor(key,IV),
                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();
        }

这是解密器的代码:

        private void DecryptFile(string inputFile, string outputFile)
    {
            string password = @"yourPWhere";

            UnicodeEncoding UE = new UnicodeEncoding();
            byte[] key = CreateKey(password);
            FileStream fsCrypt = new FileStream(inputFile, FileMode.Open);
            RijndaelManaged RMCrypto = new RijndaelManaged();
            IV = CreateIV(password_mTxtBx.Text);

            CryptoStream cs = new CryptoStream(fsCrypt,
                RMCrypto.CreateDecryptor(key, IV),
                CryptoStreamMode.Read);

            FileStream fsOut = new FileStream(outputFile.Remove(outputFile.Length - 4), FileMode.Create);

            int data;
            while ((data = cs.ReadByte()) != -1)
                fsOut.WriteByte((byte)data);

            fsOut.Close();
            cs.Close();
            fsCrypt.Close();

        }

几个月前我在 codeproject 上看到了类似的代码。所以这不是我的直接工作。 致谢作者。

更新了基于密码的密钥派生 (PBKDF2):

private static int saltLengthLimit = 32;
private static byte[] GetSalt(int maximumSaltLength)
{
    var salt = new byte[maximumSaltLength];
    using (var random = new RNGCryptoServiceProvider())
    {
        random.GetNonZeroBytes(salt);
    }

    return salt;
}
public static byte[] CreateKey(string password)
{
    var salt = GetSalt(10);

    int iterationCount = 20000; // Nowadays you should use at least 10.000 iterations
    using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, iterationCount))
        return rfc2898DeriveBytes.GetBytes(16);
}

IV 的创建者(由密码创建):

public byte[] CreateIV(string password)
{
    var salt = GetSalt(9);

    const int Iterations = 325;
    using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, Iterations))
        return rfc2898DeriveBytes.GetBytes(16);
}

在我的情况下,密钥的字节长度为 128bit(!) = 16 字节 (128/8),但您可以使用 Rijndael 支持的任何其他长度(密钥:128、192、256 位 = 16、24、 32 字节)。 IV 总是 16 字节!

【讨论】:

  • 天哪,该代码没有使用好的密钥派生函数或随机 IV。
  • 有没有办法在不创建新文件的情况下加密文件?
【解决方案2】:

如果您想在解压缩时在原始 zip 文件中使用密码,则需要重新压缩文件并在执行此操作时添加密码。

dotnetzip 库文档中的This link 展示了一种使用该库进行密码加密的简单压缩方法。


关于安全性的附加说明:
如果您完全关心加密安全性,请不要使用 zip 2.0 加密方法,因为它存在很大缺陷。而是使用 AES 256 位加密。

这里是一些示例代码(直接从上面的链接中提取),显示了使用具有默认级别压缩的 dotnetzip 库实现 AES 256 位加密:

using (ZipFile zip = new ZipFile())
{
    zip.AddFile("ReadMe.txt"); // no password for this one
    zip.Password= "Cool.Hand.Luke!";
    zip.Encryption= EncryptionAlgorithm.WinZipAes256;
    zip.AddFile("Rawdata-2008-12-18.csv");
    zip.Save("Backup-AES-Encrypted.zip");
}

编辑:添加了关于原始 zip 文件的说明
编辑 2:添加代码

【讨论】:

  • 好推荐。喜欢密码选择。 :)
【解决方案3】:

你可以使用DotNetZip (Ionic zip),支持设置密码,提供零级压缩:

using (ZipFile zip = new ZipFile())
  {
    zip.CompressionLevel = Ionic.Zlib.CompressionLevel.None;
    zip.AddFile(@"MyMusic\Messiah-01.mp3");
    zip.Save(ZipFileToCreate);
  }

所以你只需设置密码就没有开销(压缩已经压缩的文件)。

【讨论】:

  • 这不会在他当前的 zip 上输入密码,而是在加密的 zip 文件中创建一个新的 zip 文件,其中包含他当前的压缩文件。
  • 是的,它将是 zip in zip,但只要没有压缩,它就会按要求快速。您也可以阅读现有的 zip using (ZipFile zip = ZipFile.Read("ExistingArchive.zip")) 并添加密码。看例子dotnetzip.codeplex.com/wikipage?title=CS-Examples
  • 我不确定,但我认为如果文件非常大,这可能会显着增加解压缩时间,因为它必须分别执行两个过程(解密和解压缩),而不是一起执行应该进行重大优化。
  • 使用密码更新可能会更快,但无论如何它应该被测试,这取决于实现。
  • 好吧...我的逻辑存在缺陷...压缩必须在加密之前进行,否则实际上无法进行压缩,如下所述:superuser.com/questions/260663/…。因此,这两种方法之间的区别应该在时间上是微不足道的,尽管我不确定实际情况是否如此。
猜你喜欢
  • 2010-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
相关资源
最近更新 更多