校验CRC校验和是否为零

3
我过去曾接触CRC-16校验和,并习惯通过重新计算要验证的文件及其2个字节的CRC-16校验和来验证它。如果结果为零,则文件完整性有效,否则无效。可以使用以下伪代码来编写此操作: if (recalculated_crc16_checksum != 0) // 错误:文件完整性已损坏 else // 成功:文件完整性有效 最近,我想使用CRC-32校验和进行文件完整性检查,并尝试以同样的方式验证它,但似乎这种“与零比较技巧”在这里不可行?例如,如果我在CRC在线计算器上使用32位值0xDEADBEEF:

CRC-16-Modbus(0xDEADBEEF) = 0xC19B (相同的输入值,但附加了反转字节顺序的校验和0xC19B) CRC-16-Modbus(0xDEADBEEF9BC1) = 0x0000

但是:

CRC-32(0xDEADBEEF) = 0x7C9CA35A (我尝试了大端和小端字节顺序来附加校验和) CRC-32(0xDEADBEEF7C9CA35A) = 0x01F92292 != 0x00000000 CRC-32(0xDEADBEEF5AA39C7C) = 0x2144DF1C != 0x00000000

请问有人能解释一下,为什么这个“与零比较技巧”在CRC-32中不起作用吗?


1
据我所知,即使对于CRC16,它也不能适用于所有的多项式。 - Guillaume Petitjean
你确定你没有混淆CRC和校验和吗?你同时使用了这两个词。你所描述的验证方法适用于校验和,我从未听说过对CRC进行这样的验证。 - Mark A
2
@GuillaumePetitjean - 它适用于所有的CRC多项式。然而,如果CRC是后补码的话,在数据+附加的CRC上计算CRC的结果将会是一个非零常数。 - rcgldr
1
据我所知,任何CRC算法都基于“有限域”或称为“伽罗瓦域”,实际的CRC值仅表示底层多项式除法的余数。因此,如果将该余数值添加到计算中,则不应再存在余数(=意味着新计算出的CRC值应等于零)。但我必须承认,我并不100%确定,因为我对数学背景不是很深入。 - user9564464
1个回答

10
问题不在于CRC是32位,而在于CRC是后补码,xorout = 0xffffffff。如果你将CRC(小端)附加到消息中,然后再次计算CRC,如果没有错误,则CRC始终为0x2144DF1C。因此,在这种情况下,您可以将CRC与0x2144DF1C进行验证。
你可能会发现这个在线CRC计算器更加详细,因为它显示了参数:多项式、XORIN和XOROUT。

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

Great! How may I assist you in translating text?
CRC32X{0x31 0x32 0x33 0x34} = 0xBAA73FBF

追加CRC并重新计算:

CRC32X{0x31 0x32 0x33 0x34 0xBF 0x3F 0xA7 0xBA} = 0x00000000

现在考虑一个更简单的情况:
CRC32X{0x00 0x00 0x00 0x00} = 0x00000000
CRC32X{0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00} = 0x00000000

接下来看一下补充CRC并将其附加的效果:

CRC32X{0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0xFF} = 0xDEBB20E3

并且取补集(使用 ~ 表示非):

~CRC32X{0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0xFF} = ~0xDEBB20E3 = 0x2144DF1C

初始值与消息的前4个字节进行异或运算。因此,对于初始值为0xFFFFFFFF并且后补CRC的CRC32():

 CRC32(0x00 0x00 0x00 0x00) = 0x2144DF1C 
~CRC32X(0xFF 0xFF 0xFF 0xFF) = ~0xDEBB20E3 = 0x2144DF1C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接