标准库 archive/zip 不支持 zip 加密,因未实现 pkware 加密逻辑,无密钥接口且遇加密条目直接报错;需用 github.com/alexmullins/zip 等第三方包,并注意路径安全、密码管理与文件名脱敏。

archive/zip 本身不提供加密能力,标准库不支持 ZIP 密码保护;想用密码压缩 ZIP 文件,必须依赖第三方包,且需特别注意路径安全与密码处理逻辑。
为什么标准 archive/zip 无法加密 ZIP 文件
Go 官方 archive/zip 包只实现 ZIP 格式读写,完全不包含传统 ZIP 密码(即 PKWARE 加密)的加解密逻辑。它不识别 ZipCrypto 或 AES-256 加密头字段,也不暴露密钥设置接口。试图调用 zip.File.SetPassword 会 panic —— 因为该方法属于某些第三方 fork 的扩展,并非标准行为。
常见误判:看到 zip.File.SetPassword 就以为能加密,实则是用了 github.com/alexmullins/zip 或 github.com/looklzj/zip 这类带加密补丁的分支。
- 标准库中
zip.FileHeader没有IsEncrypted字段或密码相关字段 -
zip.Writer.CreateHeader不校验密码,也不写入加密元数据 - 解压时若遇到加密条目,
zip.Reader直接跳过或报zip: not implemented
用 github.com/alexmullins/zip 实现密码压缩的正确姿势
这是目前最稳定、被广泛采用的带密码 ZIP 支持方案,兼容 Windows/Mac 原生解压器(WinRAR、7-Zip、macOS 归档实用工具),支持 ZIP 2.0 传统加密(ZipCrypto)和 AES-256 加密(需显式启用)。
关键点不是“能不能加”,而是“怎么加才不被绕过”:
- 必须在
zip.Writer创建后、写入文件前调用w.Encrypt("filename", "password"),返回的io.Writer才是加密写入通道 - 不能对同一个
zip.Writer混用加密与非加密文件 —— 否则部分条目无密码,攻击者可直接提取 - AES-256 加密需额外启用:
zipw.RegisterEncrypter(zip.AES256, zip.NewAES256Encrypter),否则默认走 ZipCrypto(弱,仅防 casual peek) - 密码是字节切片,传入
"golang"和[]byte("golang")效果一致,但别用string([]byte)反复转换
示例关键片段:
zipw := zip.NewWriter(buf)
zipw.RegisterEncrypter(zip.AES256, zip.NewAES256Encrypter)
w, _ := zipw.Encrypt("config.json", "My$3cr3tP@ss")
io.Copy(w, fileReader)
zipw.Close()
加密 ZIP 的三个致命陷阱
生产环境踩坑最多的地方,不在算法,而在协议层和工程细节:
-
路径逃逸未过滤:若压缩路径来自用户输入(如
../../../etc/passwd),即使加了密码,解压时仍可能覆盖系统文件。必须在zip.Header.Name写入前调用filepath.Clean()并检查是否含".."或绝对路径前缀 -
密码硬编码或明文透出:不要把密码写死在代码里;更不要在日志、HTTP header、错误信息中回显密码字符串(哪怕只是
fmt.Printf("pwd: %s", pwd)) - ZIP 文件头未校验完整性:加密 ZIP 被篡改后,解压可能静默失败或解出乱码。建议在 ZIP 末尾追加一个独立的 SHA256 校验和(明文计算,再用相同密码加密一次附在最后),解压前先验证
替代思路:不加密 ZIP,而加密内容再压缩
如果目标是“确保只有持有密钥的人能解出原始文件”,更安全的做法是:先用 crypto/aes/gcm 加密文件内容,再用标准 archive/zip 打包(不设密码)。这样规避了 ZIP 加密实现参差不齐的问题,也避免了 ZipCrypto 弱算法风险。
优势明显:
- 密钥控制粒度更细(每个文件可用不同密钥)
- 可流式处理大文件(
io.Pipe+aead.Seal分块) - 加密强度由 AEAD 保证(GCM 自带认证,不怕篡改)
- 解压工具无门槛(任何 ZIP 工具都能打开,但内容仍是密文)
代价是:用户需额外执行解密步骤,不能双击直接打开 —— 这反而是安全性的体现。
真正容易被忽略的是:**加密后的 ZIP 文件名本身可能泄露敏感信息**。比如 salary_Q2_2026_encrypted.zip,即便内容加密,文件名已暴露业务上下文。应统一用随机名(如 pkg_8a3f9d21.zip)并单独维护映射关系。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











