Zip 文件加密可由某些 Zip 客户端读取,而其他客户端则不可读

Zip file encryption readable by some Zip clients, not others

我正在调查一个 bug report on my open source UnzipKit 项目。基本上,当将使用密码加密的文件写入 Zip 文件时,生成的存档可由某些 Zip 客户端读取,而其他客户端则不可读。

UnzipKit 将密码写入 UTF-8 字符串,使用 MiniZip zlib 包装器,它仅支持 "Traditional PKWare Encryption",不支持 AES。 它使用 zipOpenNewFileInZip3() MiniZip 函数打开文件进行写入。

BetterZip and UnzipKit on the Mac, as well as 7zip on Windows. However, WinZip (Mac and Windows) and the Mac's unzip 命令行应用程序可读,抱怨密码不正确。

出于测试目的,我使用 111111 作为密码对文件进行加密,如错误报告中所示。我尝试将文本编码更改为 ASCII 和 Latin 1 (CP-1252),但这似乎没有什么不同。

我正在努力熟悉 Zip 文件的工作方式,但这对我来说仍然很神秘。我可能做错了什么导致它在某些客户中工作而不在其他客户中工作?我希望它能够全面工作或被破坏。

这是一个 zip 文件的十六进制转储,无法解压:

50 4B 03 04 14 00 01 00 08 00 B7 54 D1 46 1B B6 2D 32 2F 00 00 00 21 00 00 00 0F 00 00 00 54 65 73 74 20 46 69 6C 65 20 41 2E 74 78 74 37 52 6F F1 31 B6 6E 3D 76 CD 3A 67 0E FF 08 42 C9 4D 61 74 C1 27 DF CB BE 24 41 46 56 60 89 C2 07 97 56 C9 2A 50 80 86 15 E2 62 66 90 77 20 50 4B 01 02 00 00 14 00 01 00 08 00 B7 54 D1 46 1B B6 2D 32 2F 00 00 00 21 00 00 00 0F 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 54 65 73 74 20 46 69 6C 65 20 41 2E 74 78 74 50 4B 05 06 00 00 00 00 01 00 01 00 3D 00 00 00 5C 00 00 00 00 00

这是我在命令行上得到的,return 代码为 82:

$ unzip -P 111111 PasswordProtected.zip
Archive:  PasswordProtected.zip
   skipping: Test File A.txt         incorrect password

更新

我使用 WinZip 为 Mac 创建了同一文件的存档,文件密码相同。这是它的十六进制转储:

50 4B 03 04 14 00 03 00 08 00 27 BA 76 44 1B B6 2D 32 2F 00 00 00 21 00 00 00 0F 00 00 00 54 65 73 74 20 46 69 6C 65 20 41 2E 74 78 74 1C 68 5F 1E FF CA 3A 6C D5 B6 01 28 0F 72 83 D9 01 9B BA 87 51 50 1F 66 61 83 43 E8 64 58 B6 ED A6 F0 9B 3B 87 89 70 F2 4F D9 AB 21 6A 6A 06 50 4B 01 02 14 03 14 00 03 00 08 00 27 BA 76 44 1B B6 2D 32 2F 00 00 00 21 00 00 00 0F 00 00 00 00 00 00 00 01 00 00 00 80 81 00 00 00 00 54 65 73 74 20 46 69 6C 65 20 41 2E 74 78 74 50 4B 05 06 00 00 00 00 01 00 01 00 3D 00 00 00 5C 00 00 00 00 00

最大的区别是文件数据完全不同,这意味着它是用不同的密钥加密的。此外,通用位标志表明它使用了最大压缩,而不是正常压缩。以防万一其余的提供任何线索,这是差异的摘要,用字段名称注释 provided by the spec.

以下所有字段都 100% 匹配:

我猜你的 zipOpenNewFileInZip3() 调用中的最后一个参数是零。它应该是文件的CRC。

当压缩条目被加密时,它前面有一个 12 字节的加密 header。 header 由 10 或 11 个随机字节组成,后跟该文件的 CRC 高端的 2 或 1 个字节。然后使用密码对 header 进行加密,并从那里继续对压缩数据进行加密。 (1 对 2 字节由 zip 格式的版本决定。)这允许解压缩器通过比较解密加密的结尾 header 与存储在本地 header 中的 CRC 来检查密码在它之前。

BetterZip 和 7Zip 的问题在于它们根本不检查加密的结尾 header。然后他们没有注意到加密 header 不符合规范,并继续正确解密压缩数据。另一方面,UnZip 和 WinZip 检测到该错误。