如何在C#/.NET Framework 4.6.1中无外部库创建带密码Zip文件
在.NET Framework 4.6.1中创建密码保护的Zip文件(无外部库)
.NET Framework 4.6.1自带的System.IO.Compression系列类不原生支持创建符合PKZIP标准的密码保护Zip文件,但可以通过以下两种实用方案实现需求:
方案一:对整个Zip流进行对称加密(推荐,实现简单)
这种方式将生成的无密码Zip字节流用AES算法加密,解密时需先还原出原始Zip流再解压。虽非标准加密Zip,但能满足"需指定密码才能获取内容"的核心需求,完全基于.NET原生类实现。
代码实现
using System; using System.IO; using System.Security.Cryptography; using System.IO.Compression; // 生成带密码保护的加密Zip字节流 public byte[] CreatePasswordProtectedZip(string password, InlineContent[] reports) { // 1. 生成无密码Zip字节流(复用你的原有逻辑,优化二进制写入方式) byte[] rawZipBytes; using (MemoryStream zipStream = new MemoryStream()) { using (ZipArchive zipFile = new ZipArchive(zipStream, ZipArchiveMode.Create, false)) { foreach (InlineContent report in reports) { ZipArchiveEntry entry = zipFile.CreateEntry(report.FileName, CompressionLevel.Optimal); using (Stream entryStream = entry.Open()) { // 直接复制二进制内容,避免StreamWriter的编码问题 new MemoryStream(report.Content.ToArray()).CopyTo(entryStream); } } } rawZipBytes = zipStream.ToArray(); } // 2. 用AES-256加密Zip字节流 using (Aes aes = Aes.Create()) { // 生成随机盐值,用于派生密钥(解密时需相同盐值) byte[] salt = new byte[16]; RandomNumberGenerator.Create().GetBytes(salt); // 从密码和盐值派生密钥与IV var keyDeriver = new Rfc2898DeriveBytes(password, salt, 10000); aes.Key = keyDeriver.GetBytes(32); aes.IV = keyDeriver.GetBytes(16); // 写入加密后的流(先存盐值,解密时读取) using (MemoryStream encryptedStream = new MemoryStream()) { encryptedStream.Write(salt, 0, salt.Length); using (CryptoStream cryptoStream = new CryptoStream(encryptedStream, aes.CreateEncryptor(), CryptoStreamMode.Write)) { cryptoStream.Write(rawZipBytes, 0, rawZipBytes.Length); } return encryptedStream.ToArray(); } } } // 配套解密方法(供参考) public byte[] DecryptZip(string password, byte[] encryptedBytes) { using (Aes aes = Aes.Create()) { // 读取盐值 byte[] salt = new byte[16]; Array.Copy(encryptedBytes, 0, salt, 0, salt.Length); // 派生密钥与IV var keyDeriver = new Rfc2898DeriveBytes(password, salt, 10000); aes.Key = keyDeriver.GetBytes(32); aes.IV = keyDeriver.GetBytes(16); // 解密得到原始Zip字节流 using (MemoryStream decryptedStream = new MemoryStream()) { using (MemoryStream encryptedStream = new MemoryStream(encryptedBytes, salt.Length, encryptedBytes.Length - salt.Length)) { using (CryptoStream cryptoStream = new CryptoStream(encryptedStream, aes.CreateDecryptor(), CryptoStreamMode.Read)) { cryptoStream.CopyTo(decryptedStream); } } return decryptedStream.ToArray(); } } }
注意事项
- 生成的文件无法被WinRAR、系统自带解压工具直接识别解密,需用上述解密代码还原出原始Zip流后再解压。
- 原代码中使用
StreamWriter写入二进制内容可能引发编码异常,已改为Stream.CopyTo处理。
方案二:调用Windows Shell COM组件(生成标准加密Zip)
Windows系统自带的Shell组件支持创建符合PKZIP标准的加密Zip,但需通过COM互操作调用,且无法自动传入密码(会弹出系统密码输入框),适合交互式场景。
代码实现
using System; using System.IO; using Shell32; // 添加COM引用:Microsoft Shell Controls And Automation public void CreateStandardEncryptedZip(string outputPath, InlineContent[] reports) { // 1. 生成临时无密码Zip文件 string tempZipPath = Path.GetTempFileName() + ".zip"; using (FileStream fs = new FileStream(tempZipPath, FileMode.Create)) using (ZipArchive zipFile = new ZipArchive(fs, ZipArchiveMode.Create, false)) { foreach (InlineContent report in reports) { ZipArchiveEntry entry = zipFile.CreateEntry(report.FileName, CompressionLevel.Optimal); using (Stream entryStream = entry.Open()) { new MemoryStream(report.Content.ToArray()).CopyTo(entryStream); } } } // 2. 创建空的目标加密Zip文件 File.Create(outputPath).Dispose(); // 3. 调用Shell组件完成加密(会弹出系统密码输入框) Shell shell = new Shell(); Folder tempFolder = shell.NameSpace(Path.GetDirectoryName(tempZipPath)); Folder targetFolder = shell.NameSpace(Path.GetDirectoryName(outputPath)); FolderItem tempZipItem = tempFolder.ParseName(Path.GetFileName(tempZipPath)); // 复制并加密:FOF_WANTPASSWORD触发密码输入框,FOF_NOCONFIRMATION自动覆盖现有文件 const int FOF_WANTPASSWORD = 0x0010; const int FOF_NOCONFIRMATION = 0x0002; targetFolder.CopyHere(tempZipItem, FOF_WANTPASSWORD | FOF_NOCONFIRMATION); // 等待Shell操作完成(需根据实际情况调整延迟) System.Threading.Thread.Sleep(2000); File.Delete(tempZipPath); }
注意事项
- 需添加对
Microsoft Shell Controls And Automation的COM引用。 - 无法在后台自动传入密码,必须用户手动输入,适合交互式场景。
内容的提问来源于stack exchange,提问作者Bruno Gonzalez Torres
相关产品推荐
相关产品推荐

