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.
本地文件头
Field Name UnzipKit Bytes WinZip Bytes
general purpose bit flag 01 00 03 00
last mod file time B7 54 27 BA
last mod file date D1 46 76 44
文件数据
UnzipKit
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
WinZip
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
中央目录结构
Field Name UnzipKit Bytes WinZip Bytes
version made by 00 00 14 03
general purpose bit flag 01 00 03 00
last mod file time B7 54 27 BA
last mod file date D1 46 76 44
external file attributes 00 00 00 00 00 00 80 81
以下所有字段都 100% 匹配:
- 本地文件头
version to extract
compression method
crc-32
compressed size
uncompressed size
uncompressed size
extra field length
file name
- 中央目录结构
version needed to extract
compression method
crc-32
compressed size
uncompressed size
file name length
extra field length
file comment length
disk number start
internal file attributes
relative offset of local header
file name
- 整个"End of central directory record"
我猜你的 zipOpenNewFileInZip3()
调用中的最后一个参数是零。它应该是文件的CRC。
当压缩条目被加密时,它前面有一个 12 字节的加密 header。 header 由 10 或 11 个随机字节组成,后跟该文件的 CRC 高端的 2 或 1 个字节。然后使用密码对 header 进行加密,并从那里继续对压缩数据进行加密。 (1 对 2 字节由 zip 格式的版本决定。)这允许解压缩器通过比较解密加密的结尾 header 与存储在本地 header 中的 CRC 来检查密码在它之前。
BetterZip 和 7Zip 的问题在于它们根本不检查加密的结尾 header。然后他们没有注意到加密 header 不符合规范,并继续正确解密压缩数据。另一方面,UnZip 和 WinZip 检测到该错误。
我正在调查一个 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.
本地文件头
Field Name UnzipKit Bytes WinZip Bytes general purpose bit flag 01 00 03 00 last mod file time B7 54 27 BA last mod file date D1 46 76 44
文件数据
UnzipKit 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 WinZip 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
中央目录结构
Field Name UnzipKit Bytes WinZip Bytes version made by 00 00 14 03 general purpose bit flag 01 00 03 00 last mod file time B7 54 27 BA last mod file date D1 46 76 44 external file attributes 00 00 00 00 00 00 80 81
以下所有字段都 100% 匹配:
- 本地文件头
version to extract
compression method
crc-32
compressed size
uncompressed size
uncompressed size
extra field length
file name
- 中央目录结构
version needed to extract
compression method
crc-32
compressed size
uncompressed size
file name length
extra field length
file comment length
disk number start
internal file attributes
relative offset of local header
file name
- 整个"End of central directory record"
我猜你的 zipOpenNewFileInZip3()
调用中的最后一个参数是零。它应该是文件的CRC。
当压缩条目被加密时,它前面有一个 12 字节的加密 header。 header 由 10 或 11 个随机字节组成,后跟该文件的 CRC 高端的 2 或 1 个字节。然后使用密码对 header 进行加密,并从那里继续对压缩数据进行加密。 (1 对 2 字节由 zip 格式的版本决定。)这允许解压缩器通过比较解密加密的结尾 header 与存储在本地 header 中的 CRC 来检查密码在它之前。
BetterZip 和 7Zip 的问题在于它们根本不检查加密的结尾 header。然后他们没有注意到加密 header 不符合规范,并继续正确解密压缩数据。另一方面,UnZip 和 WinZip 检测到该错误。