使用DotNetZip加密仅生效于单个文件,求开源文件夹级加密压缩库
问题解决与库推荐
核心问题说明
你遇到的DotNetZip行为是正常的——它的全局密码设置仅作用于压缩包内的文件,而非压缩包本身或所谓的"主文件夹"。实际上标准ZIP格式本身不支持对"文件夹"单独加密,文件夹的加密效果依赖于其包含的文件全部被加密,或是部分库通过特殊逻辑模拟实现。
免费/开源库推荐
1. SharpZipLib (ICSharpCode.SharpZipLib)
这是.NET生态中最常用的开源ZIP处理库之一,完全免费且功能齐全。它支持设置全局密码加密所有添加的文件(含文件夹内的文件),也能为单个文件/文件夹单独配置密码。
代码示例(加密整个文件夹及内部所有内容):
using ICSharpCode.SharpZipLib.Zip; // 初始化ZIP输出流 using (var fs = File.Create(zipFilePath)) using (var zipStream = new ZipOutputStream(fs)) { zipStream.SetLevel(9); // 设置压缩级别 zipStream.Password = password; // 全局密码,所有条目将使用该密码加密 // 添加目标文件夹及内部所有内容 AddDirectoryToZip(folderToZip, zipStream, ""); zipStream.Finish(); zipStream.Close(); } Console.WriteLine("文件夹已成功压缩并加密。"); // 递归添加文件夹的辅助方法 private static void AddDirectoryToZip(string directoryPath, ZipOutputStream zipStream, string parentFolder) { var files = Directory.GetFiles(directoryPath); foreach (var file in files) { var entryName = Path.Combine(parentFolder, Path.GetFileName(file)); var entry = new ZipEntry(entryName) { DateTime = DateTime.Now }; zipStream.PutNextEntry(entry); using (var fileStream = File.OpenRead(file)) { fileStream.CopyTo(zipStream); } zipStream.CloseEntry(); } var subDirectories = Directory.GetDirectories(directoryPath); foreach (var subDir in subDirectories) { var subDirName = Path.Combine(parentFolder, Path.GetFileName(subDir)); AddDirectoryToZip(subDir, zipStream, subDirName); } }
2. System.IO.Compression(.NET内置库)
若使用.NET Core 3.0+或.NET 5+,内置的System.IO.Compression.ZipArchive配合扩展可实现密码加密。原生库本身不直接支持密码,需借助AES加密逻辑自定义实现,无需额外安装大型库,完全免费。
代码示例(通过AES加密实现文件夹加密):
using System.IO.Compression; using System.Security.Cryptography; // 创建加密的ZIP文件 using (var fs = new FileStream(zipFilePath, FileMode.Create)) using (var aes = Aes.Create()) { aes.Key = GenerateKey(password); // 从密码生成AES密钥 aes.IV = new byte[16]; // 初始化向量 // 写入加密头(需对应解压逻辑识别) fs.Write(aes.IV, 0, aes.IV.Length); using (var cryptoStream = new CryptoStream(fs, aes.CreateEncryptor(), CryptoStreamMode.Write)) using (var archive = new ZipArchive(cryptoStream, ZipArchiveMode.Create)) { // 添加文件夹及内部文件 AddFolderToArchive(folderToZip, archive, ""); } } Console.WriteLine("加密压缩完成。"); // 递归添加文件夹到ZipArchive的辅助方法 private static void AddFolderToArchive(string folderPath, ZipArchive archive, string entryPrefix) { foreach (var file in Directory.GetFiles(folderPath)) { var entryName = Path.Combine(entryPrefix, Path.GetFileName(file)); var entry = archive.CreateEntry(entryName); using (var entryStream = entry.Open()) using (var fileStream = File.OpenRead(file)) { fileStream.CopyTo(entryStream); } } foreach (var subFolder in Directory.GetDirectories(folderPath)) { var subFolderName = Path.Combine(entryPrefix, Path.GetFileName(subFolder)); AddFolderToArchive(subFolder, archive, subFolderName); } } // 从密码生成AES密钥的辅助方法 private static byte[] GenerateKey(string password) { var salt = new byte[16]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(salt); } var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000); return pbkdf2.GetBytes(32); // 生成256位密钥 }
关于"压缩文件内文件夹设置密码"的说明
标准ZIP格式没有单独加密文件夹的概念,文件夹本质是目录条目,无实际内容。所有支持"文件夹加密"的库,本质逻辑都是:
- 对该文件夹下的所有文件单独设置密码
- 或通过加密文件夹元数据、隐藏目录条目模拟加密效果
SharpZipLib可实现对指定文件夹下的文件单独加密,只需在递归添加文件时,为目标文件夹的条目单独配置密码:
// 修改AddDirectoryToZip方法,针对特定文件夹设置专属密码 private static void AddDirectoryToZip(string directoryPath, ZipOutputStream zipStream, string parentFolder, string targetFolderPassword = null) { var folderName = Path.GetFileName(directoryPath); bool isTargetFolder = string.Equals(folderName, "需要加密的文件夹名", StringComparison.OrdinalIgnoreCase); var files = Directory.GetFiles(directoryPath); foreach (var file in files) { var entryName = Path.Combine(parentFolder, folderName, Path.GetFileName(file)); var entry = new ZipEntry(entryName) { DateTime = DateTime.Now }; // 目标文件夹下的文件使用专属密码,其余使用全局密码 entry.Password = isTargetFolder && !string.IsNullOrEmpty(targetFolderPassword) ? targetFolderPassword : zipStream.Password; zipStream.PutNextEntry(entry); using (var fileStream = File.OpenRead(file)) { fileStream.CopyTo(zipStream); } zipStream.CloseEntry(); } var subDirectories = Directory.GetDirectories(directoryPath); foreach (var subDir in subDirectories) { AddDirectoryToZip(subDir, zipStream, Path.Combine(parentFolder, folderName), targetFolderPassword); } }
内容的提问来源于stack exchange,提问作者Srikant suryawanshi
相关产品推荐
相关产品推荐

