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

问题描述

我想验证我的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  

但是它们都不等于:0x4C18C78C

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

解决方法

我能够创建一个与问题中的文件匹配的zip文件。标题显示压缩类型== 0,表示无压缩,未压缩大小== 2,数据== {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文件的前几个字节。通过针对完整的未压缩有效负载运行CRC32算法来计算zip中的CRC32值。在您的情况下,有效负载是两个字节序列“ ss”。

要解决这个问题,我将您的十六进制转储转换回了一个压缩文件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将那个成员提取到stdout并通过管道传输时,我们发现它包含两个字节的字符串“ 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.