go标准库不支持zip密码解压,必须使用第三方库;archiver/v4支持zipcrypto加密,需显式传入archiver.zippwd选项,但不支持aes加密,且需注意文件名编码和内存占用问题。

Go标准库不支持ZIP密码解压,必须用第三方库
Go的archive/zip包完全不处理加密ZIP(包括传统PKWARE加密和AES加密),调用zip.ReadCloser.Open或zip.File.Open时遇到加密文件会直接返回zip: encrypted file not supported错误。这不是配置问题,是标准库故意不实现——官方明确表示“加密ZIP不在设计范围内”。想解压带密码的ZIP,唯一可行路径是引入支持解密的第三方库,目前最成熟的是github.com/mholt/archiver/v4(v4起内置密码支持)和github.com/klauspost/pgzip不适用,它只处理gzip。
用archiver/v4解压带密码ZIP的最小可行代码
注意:v4版本API与v3完全不同,且默认不启用密码支持,需显式传入archiver.ZipPwd选项。常见错误是漏掉这个选项,或把密码传错位置(比如塞进archiver.Decompress而不是archiver.Unarchive)。
package main
import (
"github.com/mholt/archiver/v4"
)
func main() {
err := archiver.Unarchive("secret.zip", "output/", archiver.ZipPwd("mypassword"))
if err != nil {
panic(err)
}
}
-
archiver.Unarchive第一个参数是源ZIP路径,第二个是目标目录(自动创建),第三个及以上是可选配置项 -
archiver.ZipPwd("mypassword")必须作为独立选项传入,不能拼在路径里或当字符串参数 - 该库只支持传统ZIP加密(ZipCrypto),不支持WinZip AES加密——如果遇到
zip: invalid password但确认密码正确,大概率是源文件用了AES加密,此时需换工具(如命令行7z)先转格式
处理ZIP中部分文件加密、部分未加密的情况
archiver/v4在遇到混合加密状态的ZIP时,默认行为是跳过所有加密文件并继续解压其余内容,不会中断整个流程。但如果你需要精确控制——比如记录哪些文件因密码错误被跳过,或对单个文件做不同密码尝试——就得手动遍历zip.Reader再逐个解密。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- 先用
zip.OpenReader打开ZIP,拿到*zip.ReadCloser - 遍历
rc.File列表,对每个*zip.File调用f.OpenWithPassword("pwd")(注意不是f.Open()) - 如果返回
nil说明密码正确,可读取;否则捕获zip.ErrInvalidPassword做自定义处理 - 关键点:
f.OpenWithPassword是archiver/v4扩展的方法,标准zip.File没有此方法,必须用github.com/mholt/archiver/v4提供的类型断言或封装
性能和兼容性要注意的硬伤
密码解压比普通解压慢3–5倍,主要耗时在逐字节解密+CRC校验。更麻烦的是Windows下生成的ZIP常含非UTF-8文件名(如GBK编码),archiver/v4默认按UTF-8解析,会导致解压后文件名乱码甚至panic。这不是密码问题,但常被误认为解密失败。
- 解决乱码:用
archiver.ZipDecoder{FilenameCharset: "gbk"}显式指定编码,再传给archiver.Unarchive - 内存占用高:大ZIP(>500MB)解压时可能触发OOM,建议配合
archiver.WithProgress做流式处理,避免一次性加载全部文件索引 - Mac/Linux生成的ZIP通常没问题,但只要ZIP来自Windows机器,就该默认怀疑文件名编码问题
真正卡住的地方往往不是密码本身,而是加密方式不匹配、文件名编码错位、或者把AES加密当成ZipCrypto去试——这些细节不报具体错误,只笼统说“invalid password”,得靠排除法定位。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










