验证 CRC 校验和是否为零
Verification of a CRC checksum against zero
以前接触过CRC-16校验和,习惯于对我要校验的文件重新计算CRC-16校验和加上CRC-16本身的2个字节来校验。
如果结果为零,则文件完整性有效,否则无效。
这可以像使用以下伪 C 一样非常有效地编码:
if (recalculated_crc16_checksum != 0)
// Error: file integrity is corrupt
else
// Success: file integrity is valid
我最近想使用 CRC-32 校验和来进行文件完整性检查,并尝试以同样的方式进行验证,但似乎"Compare-Against-Zero-Trick" 在这里不可行?!
例如,如果我在 CRC 在线计算器上使用 32 位值 0xDEADBEEF:
CRC-16-Modbus(0xDEADBEEF) = 0xC19B
(Same input value but with appended checksum 0xC19B in reversed byte ordering)
CRC-16-Modbus(0xDEADBEEF9BC1) = 0x0000
但是:
CRC-32(0xDEADBEEF) = 0x7C9CA35A
(I tried both: big and little endian byte ordering for the appended checksum)
CRC-32(0xDEADBEEF7C9CA35A) = 0x01F92292 != 0x00000000
CRC-32(0xDEADBEEF5AA39C7C) = 0x2144DF1C != 0x00000000
谁能解释一下,为什么这个 "Compare-Against-Zero-Trick" 对 CRC-32 不起作用?
问题不在于 CRC 是 32 位,而是 CRC 是 post 补码的,xorout = 0xffffffff。如果将 CRC(小端)附加到消息中,然后再次计算 CRC,如果没有错误,CRC 将始终为 0x2144DF1C。因此,在这种情况下,您根据 0x2144DF1C 验证 CRC。
您可能会发现这个在线 CRC 计算器提供了更多信息,因为它显示了参数:多项式、xorin、xorout。
http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
为了解释发生了什么,通常如果您计算一个非补码的 CRC 并将其附加到消息,然后计算消息的 CRC + CRC,得到的 CRC 为零(如果没有错误)。设 CRC32X = 初始值 = 0 且 xorout = 0 的自定义 CRC32。您可以使用我 post 编辑 link 的在线 CRC 计算器复制并粘贴以下数据。
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 的 CRC32() 和 post 补充 CRC:
CRC32(0x00 0x00 0x00 0x00) = 0x2144DF1C
~CRC32X(0xFF 0xFF 0xFF 0xFF) = ~0xDEBB20E3 = 0x2144DF1C
以前接触过CRC-16校验和,习惯于对我要校验的文件重新计算CRC-16校验和加上CRC-16本身的2个字节来校验。 如果结果为零,则文件完整性有效,否则无效。
这可以像使用以下伪 C 一样非常有效地编码:
if (recalculated_crc16_checksum != 0)
// Error: file integrity is corrupt
else
// Success: file integrity is valid
我最近想使用 CRC-32 校验和来进行文件完整性检查,并尝试以同样的方式进行验证,但似乎"Compare-Against-Zero-Trick" 在这里不可行?!
例如,如果我在 CRC 在线计算器上使用 32 位值 0xDEADBEEF:
CRC-16-Modbus(0xDEADBEEF) = 0xC19B
(Same input value but with appended checksum 0xC19B in reversed byte ordering)
CRC-16-Modbus(0xDEADBEEF9BC1) = 0x0000
但是:
CRC-32(0xDEADBEEF) = 0x7C9CA35A
(I tried both: big and little endian byte ordering for the appended checksum)
CRC-32(0xDEADBEEF7C9CA35A) = 0x01F92292 != 0x00000000
CRC-32(0xDEADBEEF5AA39C7C) = 0x2144DF1C != 0x00000000
谁能解释一下,为什么这个 "Compare-Against-Zero-Trick" 对 CRC-32 不起作用?
问题不在于 CRC 是 32 位,而是 CRC 是 post 补码的,xorout = 0xffffffff。如果将 CRC(小端)附加到消息中,然后再次计算 CRC,如果没有错误,CRC 将始终为 0x2144DF1C。因此,在这种情况下,您根据 0x2144DF1C 验证 CRC。
您可能会发现这个在线 CRC 计算器提供了更多信息,因为它显示了参数:多项式、xorin、xorout。
http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
为了解释发生了什么,通常如果您计算一个非补码的 CRC 并将其附加到消息,然后计算消息的 CRC + CRC,得到的 CRC 为零(如果没有错误)。设 CRC32X = 初始值 = 0 且 xorout = 0 的自定义 CRC32。您可以使用我 post 编辑 link 的在线 CRC 计算器复制并粘贴以下数据。
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 的 CRC32() 和 post 补充 CRC:
CRC32(0x00 0x00 0x00 0x00) = 0x2144DF1C
~CRC32X(0xFF 0xFF 0xFF 0xFF) = ~0xDEBB20E3 = 0x2144DF1C