如何从 zlib crc32 计算器获取以太网幻数 0xC704DD7B

How to get ethernet magical number 0xC704DD7B from zlib crc32 calculator

我从 this answer 中提取了一个 python 片段(稍作修改)来计算以太网 crc32 帧校验序列:

msg = '00'
data = bytes.fromhex(msg)
print(data)
print(msg)
crc = zlib.crc32(data)&0xFFFFFFFF
for i in range(4):
    b = (crc >> (8*i)) & 0xFF
    print('{:02X}'.format(b))

对于消息 00 它输出 8D EF 02 D2,这是 this answer 的位反转解决方案。到目前为止一切顺利。

现在说here,即

Running the CRC algorithm over the received frame data including the CRC code will always result in a zero value for error-free received data, because the CRC is a remainder of the data divided by the polynomial. However, this technique can fail to detect errors, in which data with trailing zeroes will also result in the same zero remainder. To avoid this scenario, the FCS is complemented (each bit is negated) by the sender before it is attached to the end of the payload data. This way, the algorithm result will always be a CRC32 residue of 0xC704DD7B when data has been received correctly.

但是如果我在计算器中输入00 8D EF 02 D2,结果是1C DF 44 21,而不是所说的余数。 我还尝试了其他组合,因为通常字节中的位必须被反转或其他什么(实际上我对所有这些反转的东西真的很困惑,但我希望,尝试几种可能性后的好结果会指导我正确的反转),但没有成功:

00 D8 FE 20 2D -> 66 40 C3 4A
00 D2 02 EF 8D -> DF 42 14 03
00 2D 20 FE D8 -> CB 50 00 AE

所以,谁能告诉我,我哪里错了?

Wiki文章中的0xC704DD7B是0x2144DF1C的位反转补码,是你得到的值,也是你应该得到的值。

在 CRC32 的情况下,由于 CRC 是 post 补码的,因此对数据执行的 "good" CRC 重新计算 + 先前计算的 CRC 将是一个非零常数,在这种情况下, 0x2144DF1C。它不是 "magic number",良好 CRC 的非零常数值是 post 补充 CRC 的结果(否则重新计算的良好 CRC 将为零)。


令人困惑的是 IEEE 标准使用左移 CRC32 BZIP2(非反向)CRC 来创建 CRC,然后声明数据首先传输最低有效位,而 CRC(称为 FCS(帧校验序列) )) 首先传输最高有效位(第 31 位)。使用右移 CRC32(反向)CRC 产生相同的 CRC 但位反转,并且首先传输数据和 CRC 最低有效位导致相同的传输。因此,根据实际实现,CRC 可能取反,也可能不取反,如果在硬件寄存器中使用 "residue",则可能会补也可能不会补。

Wiki 文章现已更新以包含这些问题。