zipfile仅支持ZipCrypto加密,不支持AES-256;遇RuntimeError: Bad password且密码正确时,大概率是AES加密导致,需改用7z或unzip命令行工具处理。

用 zipfile 解压带密码的 ZIP 文件,但仅支持传统 ZIP 加密(ZipCrypto)
Python 标准库 zipfile 能解压有密码的 ZIP,但只支持老式 ZipCrypto 加密(即 WinRAR/7-Zip 默认“传统加密”),不支持更安全的 AES-256 加密。如果遇到 BadPasswordError 却确认密码正确,大概率是压缩包用了 AES 加密——zipfile 会直接报错,不会提示“加密类型不支持”。
实操建议:
- 先用
unzip -l -P "password" archive.zip(Linux/macOS)或 7-Zip GUI 查看压缩包加密方式:若显示AE2或AES-256,就别浪费时间试zipfile - 代码中必须用
setpassword()设置字节型密码:zf.setpassword(b"mypass"),传字符串会静默失败 - 解压单个文件比全量解压更稳妥:
zf.read("file.txt", pwd=b"123")可提前验证密码是否有效
解压 AES 加密 ZIP 必须用 pyminizip 或 7z 命令行
pyminizip 本身不支持解压 AES ZIP,它只负责创建。真正能解 AES ZIP 的纯 Python 方案极少,目前稳定可用的是调用系统 7z(7-Zip 命令行版)或 unzip(需编译支持 AES 的版本)。Python 层只需做进程调用和错误捕获。
实操建议:
- Windows 下装好 7-Zip 后把
7z.exe加入 PATH,然后用:subprocess.run(["7z", "x", "-pMyPass", "-o./out", "archive.zip"]) - macOS/Linux 推荐用
unzip(Homebrew 安装的版本通常支持 AES):subprocess.run(["unzip", "-P", "mypass", "archive.zip", "-d", "./out"]) - 务必检查返回码:
result.returncode != 0时,result.stderr里常含真实错误,比如Cannot open encrypted file表示密码错,Unsupported method表示加密类型不兼容
密码是中文或特殊字符时,编码和空格要特别小心
密码含中文、空格或符号时,zipfile 要求严格按原始字节传入;而命令行工具对 shell 解析敏感。常见现象是“明明输对了却解不开”,根源往往是编码隐式转换或空格被截断。
实操建议:
- 用
zipfile时,统一用pwd=password.encode("utf-8"),避免依赖默认编码;测试前先打印len(pwd)确认字节数符合预期 - 命令行调用时,密码参数必须加引号:
["unzip", "-P", "my pass", ...]比["unzip", "-P", "my pass", ...]少一个空格风险 - 如果密码来自用户输入(如
input()),注意 Windows 控制台可能用gbk编码读入,需显式.encode("gbk")再传给setpassword()
批量解压多个带密码 ZIP 时,别忽略路径遍历和覆盖风险
解压 ZIP 时若内部路径含 ../,恶意压缩包可能写到任意目录(如 ../etc/passwd)。标准 zipfile.extractall() 不校验路径,直接释放。
实操建议:
- 手动校验每个
ZipInfo.filename:if ".." in info.filename or info.filename.startswith("/"):就跳过或报错 - 用
os.path.realpath()检查目标路径是否在解压根目录内:os.path.commonpath([real_target, real_outdir]) == real_outdir - 不要直接用用户提供的密码去解压不可信来源的 ZIP,尤其在服务端场景——一次失败尝试就可能触发重试逻辑或日志泄露密码明文
密码正确但解不开,八成是加密算法不匹配;路径含点点斜杠却没拦截,上线后可能变漏洞。这些地方没有银弹,只能靠具体场景具体卡点。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











