如何验证 Zip 文件的 CRC-32 计算

How to validate CRC-32 calculation of Zip file

我想验证我的 ZIP 文件是否具有正确的 CRC-32 校验和。
我在 ZIP 文件中读到 CRC-32 数据在字节 14 到 17 中:

Offset  Bytes   Description[30]
0        4  Local file header signature = 0x04034b50 (read as a little-endian number)
4        2  Version needed to extract (minimum)
6        2  General purpose bit flag
8        2  Compression method
10       2  File last modification time
12       2  File last modification date
14       4  CRC-32 of uncompressed data
18       4  Compressed size
22       4  Uncompressed size
26       2  File name length (n)
28       2  Extra field length (m)
30       n  File name
30+n     m  Extra field  

我想验证我创建的一个简单 ZIP 文件的 CRC-32 校验和:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
-----------------------------------------------
50 4B 03 04 14 00 00 00 00 00 38 81 1C 51 4C 18  | PK........8..QL.
C7 8C 02 00 00 00 02 00 00 00 07 00 00 00 31 32  | nj............12
33 2E 64 61 74 73 73 50 4B 01 02 14 00 14 00 00  | 3.datssPK.......
00 00 00 38 81 1C 51 4C 18 C7 8C 02 00 00 00 02  | ...8..QL.nj.....
00 00 00 07 00 00 00 00 00 00 00 01 00 20 00 00  | ............. ..
00 00 00 00 00 31 32 33 2E 64 61 74 50 4B 05 06  | .....123.datPK..
00 00 00 00 01 00 01 00 35 00 00 00 27 00 00 00  | ........5...'...
00 00                                            | ..

CRC-32 为:0x4C18C78C
我转到 this CRC-32 在线计算器并从文件中添加了以下未压缩的行:

50 4B 03 04 14 00 00 00 00 00 38 81 1C 51

这是结果:

Algorithm           Result      Check       Poly            Init        RefIn   RefOut  XorOut     
CRC-32              0x6A858174  0xCBF43926  0x04C11DB7  0xFFFFFFFF      true    true    0xFFFFFFFF
CRC-32/BZIP2        0xE3FA1205  0xFC891918  0x04C11DB7  0xFFFFFFFF      false   false   0xFFFFFFFF
CRC-32C             0xB578110E  0xE3069283  0x1EDC6F41  0xFFFFFFFF      true    true    0xFFFFFFFF
CRC-32D             0xAFE2EEA4  0x87315576  0xA833982B  0xFFFFFFFF      true    true    0xFFFFFFFF
CRC-32/MPEG-2       0x1C05EDFA  0x0376E6E7  0x04C11DB7  0xFFFFFFFF      false   false   0x00000000
CRC-32/POSIX        0xFF9B3071  0x765E7680  0x04C11DB7  0x00000000      false   false   0xFFFFFFFF
CRC-32Q             0x79334F11  0x3010BF7F  0x814141AB  0x00000000      false   false   0x00000000
CRC-32/JAMCRC       0x957A7E8B  0x340BC6D9  0x04C11DB7  0xFFFFFFFF      true    true    0x00000000
CRC-32/XFER         0xA7F36A3F  0xBD0BE338  0x000000AF  0x00000000      false   false   0x00000000  

但其中 none 个等于:0x4C18C78C.

我做错了什么? ZIP的CRC-32是对之前所有字节(0-13)的计算,不是吗?

我能够创建一个与问题中的文件匹配的 zip 文件。 header显示compression type == 0,表示不压缩,uncompressed size == 2,data == {73 73}。 CRC32采用反射输入输出,CRC采用小端格式存储,所以CRC == 0x8CC7184C.

我使用此在线 CRC 计算器对 {73 73} 的数据使用 CRC32 进行了匹配:

http://www.sunshine2k.de/coding/javascript/crc/crc_js.html

你运行在线CRC计算器的字节序列不是未压缩的字节。

50 4B 03 04 14 00 00 00 00 00 38 81 1C 51

这些字节是 zip 文件的前几个字节。 zip 中的 CRC32 值是通过 运行 CRC32 算法针对完整的未压缩负载计算得出的。在您的情况下,有效负载是两个字节序列“ss”。

为了解决这个问题,我将您的十六进制转储转换回一个 zip 文件,tmp.zip。它包含一个成员 123.dat

$ unzip -lv tmp.zip 
Archive:  tmp.zip
 Length   Method    Size  Cmpr    Date    Time   CRC-32   Name
--------  ------  ------- ---- ---------- ----- --------  ----
       2  Stored        2   0% 2020-08-28 16:09 8cc7184c  123.dat
--------          -------  ---                            -------
       2                2   0%                            1 file

当我通过 hexdump 将该成员提取到标准输出和管道时,我们发现它包含两个字节字符串“ss”(十六进制 73 73)

$ unzip -p tmp.zip | hexdump -C
00000000  73 73                                             |ss|
    

最后,正如另一个评论中已经提到的,您可以通过 运行 unzip -t

检查 CRC 值是否正确
$ unzip -t tmp.zip 
Archive:  tmp.zip
    testing: 123.dat                  OK
No errors detected in compressed data of tmp.zip.