问题描述
我想验证我的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
$ unzip -t tmp.zip
Archive: tmp.zip
testing: 123.dat OK
No errors detected in compressed data of tmp.zip.