把敏感文件打成带密码的 ZIP 再外发,默认加密、文件名和未加密条目还可能留下什么

外发工资表、证书包或导出配置时,最省事的动作经常是「压缩,设个密码,丢进邮件或网盘」。对方双击要输口令,看起来整包都锁住了。ZIP 的加密标志写在每一条文件上;传统加密被规格写成弱;文件名和未加密条目常常还在明文头里。下面按 PKWARE、WinZip 和 7-Zip 自己写得出来的分层,把「打了密码之后还剩什么」收成可以当场核对的范围。

「设了密码」不是「整包都锁住了」

很多人把带密码的 ZIP 当成一只上锁的箱子:箱子在谁手里都没关系,没有钥匙就看不见里面。实际格式更碎。ZIP 先是一份目录,再是一条条文件。加密标志挂在每一条文件的本地头和中央目录上,不挂在「整个 .zip 文件」这一层。你设了密码,只说明至少有一条文件的压缩数据流按某种算法罩住了;不等于目录不可读,也不等于包里每一条都用了同一种算法、同一句口令。

财务报表、身份证扫描件、SSH 私钥、数据库转储、未脱敏的客户表,都属于不该在「当前这一个文件夹」以外多留几份明文线索的内容。要处理的不是「这个压缩软件聪不聪明」,而是「这一次打包有没有把不该离开当前文件的内容,以明文文件名、明文条目或弱加密流的形式交出去」。上一篇写过:把未加密文件直接丢进网盘,服务商、同步客户端和秒传还可能看到原文。先打一个带密码 ZIP 再上传,只是把问题从「云端看不看得见文件」换成「这个容器到底锁了哪一层」。

本文以 PKWARE 的 APPNOTE.TXT 6.3.10(2022-11-01)、WinZip AES 规格 AE-1 / AE-27-Zip 对 7z 格式 AES-256 的说明为主,因为分层写得清楚,也好对照本机输出。企业策略、在线「加密压缩」网页和老版本界面会再叠一层。换工具时应对着那一版的加密选项再看一遍 Method,不要把下面的 ZipCrypto 句子直接套到已经勾了 AES-256 或打开了「加密文件名」的包上。

传统加密、AES 扩展、文件名加密:三层不是同一层

把「ZIP 加没加密」听成一个是或否,会漏掉至少三层。第一层是传统 PKWARE 加密,也就是软件里常标成 ZipCrypto 或 Zip 2.0 的那一种。APPNOTE 第 6 节把它的对象写得很窄:PKZIP 加密的是压缩后的数据流。每一条被加密的文件,数据区开头多 12 字节加密头;三组 32 位密钥用口令初始化,再用和 ZIP 相同的 CRC-32 去更新。扩展名还是 .zip,资源管理器或旧解压程序往往能弹出口令框,兼容性好,强度是另一回事。

第二层是后来加进 ZIP 容器的 AES。WinZip 不改基本结构,只加一件事:压缩方法写成十进制 99,再在本地头和中央目录各放一段额外字段 0x9901,一共 11 字节,厂商代号是 ASCII AE。强度字节 0x01 / 0x02 / 0x03 分别对应 128、192、256 位密钥。真正的压缩方法(例如 Deflate 的 8)挪进这段额外字段。不解 AES 的旧工具通常会报「不支持的压缩方法 99」,而不是误把密文当明文解出来。这一层保护的是文件内容,默认并不把中央目录里的文件名改成密文。

第三层是「连目录一起罩住」。ZIP 的 Strong Encryption 把中央目录加密写成可选项,还要用 general purpose bit 6、bit 13 等标志;传统 ZipCrypto 没有这一层。7-Zip 的 .7z 格式走另一条路:官方页写明用 AES-256,密钥由基于 SHA-256 的派生函数从口令算出来,并且用大量迭代提高穷举代价。命令行的 -mhe=on 会加密文件名。没打开这一项时,即使内容是 AES,列出档案仍可能先看到名字。

分层 通常锁住什么 默认仍可能看见什么 怎么当场认
ZipCrypto / 传统 PKWARE 该条文件的压缩数据流 文件名、未加密条目、包结构 7z l -slt 里 Method 含 ZipCrypto
WinZip AES(AE-1 / AE-2) 该条文件内容(AES + HMAC) 文件名;同一包里未加密的其他条目 压缩方法 99,额外字段 0x9901,Method 含 AES-
7z + 加密文件名 内容和目录头 未打开 -mhe=on 时仍可能先看到文件名 7-Zip 对话框里的「加密文件名」,或命令行 -mhe=on

产品页或右键菜单写「AES-256」只回答内容用了什么算法,不回答文件名在不在明文头里,也不回答包里有没有没设密的条目。核对时先看 Method 和文件名列表,再看口令有多长。

ZipCrypto:规格自己写成弱,挡不住已知明文这条研究线

传统加密不是「民间误传很弱」,是格式定义者自己降过级。APPNOTE 6.0.1 的原文是:这种形式 considered weak by today's standards,只建议用于低安全需求,或为了兼容更老的 ZIP 程序。算法骨架也写在同一节:密钥初值是 305419896591751049878082192 三组 32 位整数;update_keys 每处理一个口令字节就调用一次 CRC-32;数据区开头 12 字节加密头用来继续搅动密钥,最后 1 或 2 个字节对照 CRC 高位,用来判断口令对不对。这是流密码,不是 AES-GCM 那种带认证标签的分组模式。

规格里写过:12 字节头的目的是「让针对数据的明文攻击变得无效」。公开文献走的是另一条路。Eli Biham 与 Paul C. Kocher 在 1994 年发表 A Known Plaintext Attack on the PKZIP Stream Cipher,说明在知道一段明文的条件下可以恢复内部状态。Michael Stay 在 2002 年的 ZIP Attacks with Reduced Known Plaintext 把所需明文量又压低。压缩包里经常自带可预测前缀:PDF 的 %PDF、Office 文档的固定头、XML 声明、PNG 签名。攻击细节不属于本文范围;要点是:弱点在算法,不在「你的口令只有 6 位」。口令再长,也改变不了「传统加密被规格写成弱、并且存在已知明文这条研究线」这件事。

兼容性解释了它为什么还在。Windows 资源管理器可以创建和打开普通 ZIP,但没有原生「给 ZIP 设密」的界面;Microsoft Q&A 上的独立顾问答复写过:要设密得用 7-Zip 这类第三方工具,资源管理器对第三方打出来的 ZipCrypto 包往往还能弹出口令框。于是不少软件把 ZipCrypto 留作默认,好让对方双击就能解。你图的是「对方不用装软件」,付的是规格自己承认的弱加密。7-Zip 打 ZIP 时可以改成 AES-256;改完之后,只认 ZipCrypto 的系统解压器可能直接打不开。这是兼容和强度之间的取舍,不是「两种都叫加密所以一样」。

文件名、CRC 和未加密条目:没进密文流的东西还在明文里

即使内容层换成了 AES,ZIP 默认仍是「能列目录的容器」。本地头和中央目录里的 FileName 是明文字段;general purpose bit 0 只表示这一条的数据流加密了。bit 11 表示文件名用 UTF-8,不表示文件名被加密。Tadayoshi Kohno 在 2004 年对 WinZip 加密方案的分析里,把三件格式事实写得很清楚:加密文件的元数据会泄漏、文件名未经认证、同一档案可以同时包含加密和未加密文件。这些不是实现 bug,是容器允许的形状。

WinZip 自己的 AES 说明把「混合包」写成正式许可:没有要求一个 ZIP 里的文件全部加密,也没有要求加密文件用同一种方法或同一句口令;一个包可以任意组合未加密文件,以及 Zip 2.0、AES-128、AES-192、AES-256。文件夹条目甚至被建议不要加密,以减小体积。结果是:你把 薪资-2026-09.xlsxreadme.txt 打进同一个包,可能只有表格问口令,说明文件和目录名谁都能读。外发时对方、邮件网关、网盘预览和同步客户端,先看到的常常是这张目录,不是解开后的单元格。

明文头里还有体积和校验。WinZip 写明:AE-1 在 ZIP 头里存放未加密内容的 CRC,AE-2 把 CRC 写成 0,改用 10 字节认证码查完整性。原因写在 FAQ:对只有四个字节或更短的文件,CRC 本身就能帮助推断原文,与用哪种加密无关。WinZip 11 起对大多数文件改回 AE-1 以多做一次完整性核对,但对未压缩大小小于 20 字节的文件,以及自带校验的 BZIP2,仍用 AE-2、不存 CRC。密钥派生是 PBKDF2(RFC 2898),迭代 1000 次,伪随机函数是 HMAC-SHA1;规格也写了 HMAC-SHA1 输出 160 位,因此 192 / 256 位 AES 的有效搜索空间不能按理论密钥长度去理解。这些数字不需要你去「破解」才能核对——它们已经写在公开规格里。

当场核对:不解出原文,先看 Method 和文件名

口号写「我设了密码所以安全」没法证明。把核对拆成可以在本机做完的几步,每一步只回答一个问题。不要对真实工资表、证书或私钥做实验。

不要用正在使用的证件扫描件、生产环境密钥或真实员工表打包「看看长什么样」。准备一份可以丢弃的金丝雀,例如文件名 canary-payroll-20260905.txt、正文只写一行一次性标记。核对的是目录和 Method,不是把真文件再压缩一遍。

  1. 用记事本写一份金丝雀文本,文件名故意带业务含义,例如 canary-payroll-20260905.txt。需要随机口令时,用密码生成器抽 6–128 位(默认 16;低于 8 位会提示较弱),只把这串当成压缩口令,不要当成新的登录口令。
  2. 按你平时外发的方式打一个 ZIP:有的软件默认 ZipCrypto,有的要手动选 AES-256。不要改文件名去「隐藏」主题。再另打一份 7z,分别打开和关掉「加密文件名」,方便对照。
  3. 不要输入口令。用 7-Zip 打开或在终端执行 7z l -slt canary.zip。看文件名列表是否已经出现 canary-payroll-20260905.txt。再找 Method = 这一行:出现 ZipCrypto 就是传统加密;出现 AES-256 才是内容层 AES。不解出正文也能读到这两项,说明它们不在「必须先输口令」那一层。
  4. 对 7z 再列一次。没开文件名加密时,名字往往仍在列表里;开了 -mhe=on 之后,未输口令应看不到那条金丝雀文件名。这是第三层在不在的对照,不是「7z 一定比 ZIP 神秘」,差在目录头有没有被罩住。
  5. 把金丝雀包丢进你平时用的网盘或邮件草稿(不要发给别人)。看预览或网页端是否直接列出内部文件名。上一篇写过:未加密文件的秒传和预览要看到原文;这里即使内容锁住,目录名仍可能先被索引。核对结束后删除金丝雀包和源文件,并检查回收站。

第一段核对的细节——本机有没有把明文正文交给压缩软件——和浏览器里做加密,怎么当场核对明文没有离开本机不同:压缩软件几乎一定会在本机读入原文才能打包。本文要核对的是「打包之后,没进密文流的东西还剩什么」。金丝雀文件名若在未输口令时就出现在 7z l -slt 或网盘预览里,说明信任边界比「对方没有密码」大。Method 仍是 ZipCrypto,说明你图的是兼容,不是规格意义上的强加密。

用打开即用的文件加密盒,把「整份文件」和「压缩包密码」分开

若你要的是「先在本机把整份文件打成密文,再决定用邮件还是网盘外发」,不必先注册,也不必把文件交给 MakePwd。打开文件加密盒,在当前标签页用 AES-256-GCM 分块加密,下载 .lock.enc。口令经 PBKDF2-HMAC-SHA256、100,000 次迭代派生,每个文件独立盐值;单文件最大 5 GB。文件、口令和明文都不会作为业务数据上传。全部工具打开即用,没有账号,也没有密码库替你保管这串口令。

文件加密盒回答的是「这一份字节在离开浏览器之前有没有变成密文」,不回答「ZIP 默认锁不锁文件名」。下载名由你决定,不必再用 薪资表-2026.xlsx.zip 这种自己泄露主题的名字。密文可以走网盘或邮件;口令请走另一条通道,例如阅后即焚:密钥放在 URL 的 # 片段,不随 HTTP 发给服务器,创建与阅读都公开,服务端只暂存密文。需要随机口令时,用密码生成器抽 6–128 位,只在本页复制。把未加密文件直接丢进网盘会怎样,见上一篇;本文只把「带密码 ZIP 还剩什么」收进结论。

常见问题

ZIP 设了密码,是不是整包都加密了?

不是。PKWARE APPNOTE 把加密标志写在每一条文件的 general purpose bit 0 上,加密的是该条压缩数据流,不是整个容器。文件名写在本地头和中央目录里。WinZip 的 AES 说明写明:同一 ZIP 可以混用未加密条目,以及 Zip 2.0、AES-128、AES-192、AES-256 四种方法,口令也可以不同。

ZipCrypto 和 AES-256 ZIP 差在哪?

ZipCrypto 是 APPNOTE 第 6 节的传统 PKWARE 加密:三组 32 位密钥、12 字节加密头、用 CRC-32 更新密钥。规格自己写成「以今天的标准看是弱的」,只建议低安全需求或兼容旧程序。WinZip AES 用额外字段 0x9901、压缩方法 99,以及盐、口令校验值和 HMAC-SHA1 认证码。扩展名都是 .zip,必须看 Method,不能看后缀。

不输入密码,能不能看到里面有什么文件?

传统 ZIP 和未打开文件名加密的包,通常可以。7-Zip 的 7z l -slt 会列出文件名和 Method,不需要先解出明文。7z 格式可以打开「加密文件名」(-mhe=on),那一层才会把目录头也罩住。Windows 资源管理器没有原生「给 ZIP 设密」的界面。

带密码 ZIP 和 MakePwd 文件加密盒是一回事吗?

不是。压缩包密码回答的是「这个容器用了哪一种 ZIP 加密」。文件加密盒在当前标签页用 AES-256-GCM 加密整份文件,输出 .lock / .enc,单文件最大 5 GB,文件与口令不上传,打开即用。口令应走另一条通道,例如阅后即焚链接的 # 片段。

下次打压缩包前记住的三件事

第一,「设了密码」只说明至少有一条文件的数据流按某种 ZIP 加密罩住了,不说明整包目录不可读,也不说明每一条都加密。第二,ZipCrypto(规格写成弱、存在已知明文研究线)、WinZip AES(内容层更强,文件名默认仍在明文头)和 7z 的文件名加密是三套不同的边界;扩展名都叫 .zip.7z 说明不了你在哪一层。第三,用一次性金丝雀按 7z l -slt 的 Method 和未输口令就能看到的文件名核对,不要用真实表格做实验。

若你还要继续追问「未加密文件丢进网盘之后服务商还看得见什么」,请读把未加密文件直接丢进网盘,服务商、同步客户端和秒传还可能看到什么。生成或加密过程要当场核对明文没有离开本机时,可读浏览器里做加密,怎么当场核对明文没有离开本机。口令要另发给对方、又不想走邮件正文时,见URL 的井号后面为什么适合放密钥,以及什么时候会失效。本文只把「打了带密码 ZIP 之后,默认加密、文件名和未加密条目还可能剩什么」收成可以写进结论的范围。