每天都在解压,但加密强度、文件名编码和格式兼容这三件事最容易翻车。理解归档格式背后的设计权衡,能少走很多兼容性弯路。
ZIP 加密的两套体系
ZIP 文件可以加密,但”加密”两个字下面藏着完全不同的东西:
| 加密方式 | 出现年代 | 强度 | 兼容性 |
|---|---|---|---|
| ZipCrypto | 1989 | 形同虚设(已知明文攻击秒破) | 所有 ZIP 工具都支持 |
| AES-128 | 2003(WinZip 9) | 强 | 大多数现代工具 |
| AES-256 | 2003(WinZip 9) | 强 | 大多数现代工具,部分老旧工具不识别 |
关键事实:
- 截至 2026-05-02,Windows 11 24H2 官方说明已明确:系统自带归档能力不支持对加密归档做操作
- 如果攻击者拿到这个 ZIP 里任何一个文件的明文片段(哪怕只有 12 字节),可以在几秒内推出密钥
- 即使没有明文,弱密钥的暴力破解也比 AES 快几个数量级
- 用 advzip / pkcrack 等开源工具可以验证
判断 ZIP 加密类型的方法:
# 7-zip 命令行
7z l -slt encrypted.zip | grep -i method
# 输出 "ZipCrypto" 还是 "AES-256"
# unzip 信息
unzip -lv encrypted.zip
# 加密标志列会显示
GUI 工具:用 7-Zip GUI 打开 ZIP,“方法”列直接告诉你。
实操建议:所有需要密码的归档,优先用 7z 或明确标注为 AES ZIP 的工具创建;不要把“系统能压缩 / 能打开 ZIP”误解成“系统也能稳定处理加密 ZIP”。
中文文件名乱码的历史包袱
ZIP 规范早年没规定文件名编码——各系统按本地编码写。中文 Windows 用 GBK / CP936,Mac / Linux / 现代系统用 UTF-8。两边互传就乱码:
| 创建端 | 解压端 | 结果 |
|---|---|---|
| Windows 7-Zip(默认) | Mac / Linux | 乱码(“鏂囨。.txt”) |
| Windows 7-Zip(勾 UTF-8) | Mac / Linux | 正常 |
| Mac / Linux | Windows 资源管理器 | 乱码(“文档.txt”) |
| Mac / Linux | Windows 7-Zip | 乱码 |
ZIP 头部有一个 bit(General Purpose Bit Flag 第 11 位)标记”文件名是 UTF-8”。新版工具会读这个 bit 决定怎么解码:
- 设了 → 按 UTF-8 解
- 没设 → 按系统默认编码解(这就是乱码源头)
Windows 7-Zip 默认不打这个 bit——为了兼容老软件。要打开需要在选项里勾 “cu = on”(命令行 -mcu=on)。
修复方法:
# Linux / Mac 解压 GBK 中文 ZIP
unzip -O cp936 chinese.zip
# 7-Zip Mac 版(指定字符集)
# 在 GUI 设置里改"代码页"为 936
# 用 The Unarchiver(Mac)打开会自动识别
本工具基于 libarchive,对常见中文 ZIP 会做编码探测——但仍建议创建端用 UTF-8 标志位,从源头避免。
格式选型矩阵
| 格式 | 压缩比 | 速度 | 跨平台 | 加密 | 适用 |
|---|---|---|---|---|---|
| ZIP(Deflate) | 中 | 快 | 顶级 | AES ZIP / ZipCrypto | Windows 用户分享、跨平台传输 |
| ZIP(Deflate64) | 中+ | 中 | 一般 | 同上 | 老 WinZip,避免使用 |
| 7z(LZMA2) | 最高 | 慢 5-10× | 需装 7-Zip | AES-256-CBC + 文件名 | 自己存档、网盘备份 |
| RAR | 高 | 中 | 一般(常需额外工具) | AES-256 | 对方明确要求时再用 |
| tar.gz | 中 | 快 | Linux/Mac 原生 | 无(需配合 GPG) | 源码分发、Linux 部署 |
| tar.bz2 | 高 | 中 | Linux/Mac 原生 | 无 | 已被 xz 取代 |
| tar.xz | 高+ | 慢 | Linux/Mac 原生 | 无 | Linux 大文件归档 |
| tar.zst | 高 | 极快 | 需 zstd(新) | 无 | 现代高速归档(Facebook 提出) |
实战建议:
- 传给同事 / 客户 → ZIP(任何系统都能开)
- 网盘备份大量文件 → 7z(体积小一半)
- 代码 / 配置归档 → tar.gz(Linux 工具链友好)
- Mac → Mac 之间 → 直接 ZIP(macOS Finder 创建的就是 UTF-8 ZIP,无乱码)
- 要密码 → 7z 优先,ZIP+AES-256 次之
7z 实体压缩的取舍
7z 的”实体压缩”(Solid Compression)是它压得小的关键:
普通压缩(按文件独立):
file1.txt → 压缩 → 块1
file2.txt → 压缩 → 块2
file3.txt → 压缩 → 块3
实体压缩(合并成大流):
file1.txt + file2.txt + file3.txt → 拼成一个大文件 → 压缩 → 单块
收益:相似文件(如同一项目的多个 .js 源码)之间能跨文件去重,体积能再降 20-50%。
代价:
- 解压其中一个文件要先解压它前面的所有文件——单文件随机访问慢
- 实体块越大压缩比越高但访问越慢,7-Zip 默认块大小 2GB
- 损坏一个字节会导致后面所有文件丢失
适用 / 不适用:
| 场景 | 适用 |
|---|---|
| 一次打包,整包归档 | ✓ 推荐 |
| 频繁单独取文件 | ✗ 关闭实体压缩 |
| 网盘冷备 / 异地备份 | ✓ 推荐 |
| 软件分发 / 安装包 | ✗ 用户解压时只想要部分文件 |
tar 的”两步走”
tar.gz、tar.xz 这种”双扩展名”是 Linux 习惯:
原始文件 → tar 打包(不压缩)→ gzip 压缩 → .tar.gz
tar 只把多个文件拼成一个大流(保留权限、时间、符号链接、设备文件等),不做压缩。然后用 gzip / bzip2 / xz / zst 任选一个压缩工具。
设计动机:
- 职责单一:tar 管打包,gzip 管压缩,互不干扰
- 流式处理:可以
tar c | gzip | ssh remote 'tar x'流式传输 - 可换压缩:同样的 tar 文件可换 xz、zst 重新压缩
代价是 tar 不支持部分提取——要解压其中一个文件理论上要扫描整个流(实践中支持但慢)。
解压时的几个坑
1. 路径穿越(Zip Slip)
恶意 ZIP 里文件名写 ../../../../etc/passwd,解压时可能跳出目标目录覆盖系统文件。浏览器端工具通常会额外做路径规范化,但服务端、脚本和老旧解压流程仍要自己做校验。
2. ZIP 炸弹
像 42.zip 这类递归压缩炸弹会在解压后极度膨胀。浏览器工具是否能顺利打开,仍受内存和实现策略限制;真正处理上传归档的服务端必须做大小、层级和时间限制。
3. 长文件名截断
Windows 路径限制 260 字符,深嵌套的 npm 项目压缩包解压时常报”路径过长”。Win10+ 可在注册表打开 LongPathsEnabled,或用 7-Zip 直接解(它内部走 NT 长路径 API)。
4. 符号链接被实体化
tar 保留符号链接,但解压到 Windows 时会被实体化为副本——节省的空间会膨胀。
一句话总结
ZipCrypto 只留给兼容性场景、创建端尽量写 UTF-8 文件名、跨平台分享优先 ZIP / 自己存档优先 7z / Linux 部署常用 tar.gz——把这三条理顺,绝大多数归档兼容问题都会少很多。