我想逐字节计算以太网数据包的帧校验序列(FCS)。多项式是0x104C11DB7
。
我尝试了在这里http://en.wikipedia.org/wiki/Cyclic_redundancy_check或者在这里http://www.woodmann.com/fravia/crctut1.htm看到的XOR-SHIFT算法。
假设需要进行CRC校验的信息仅为一个字节。让我们假设它是0x03
。
步骤1:将32位填充到右侧
0x0300000000
将多项式和数据在左侧与第一个不为零的比特对齐并进行异或操作
0x300000000 xor 0x209823B6E = 0x109823b6e
取余数并再次对齐和异或
0x109823b6e xor 0x104C11DB7 = 0x0d4326d9
由于没有剩余比特,0x03的CRC32应为0x0d4326d9
。
不幸的是,所有软件实现都告诉我我错了,但我错在哪里或他们做了什么不同?
Python 告诉我:
"0x%08x" % binascii.crc32(chr(0x03))
0x4b0bbe37
这里的在线工具http://www.lammertbies.nl/comm/info/crc-calculation.html#intr与我手算得到的结果相同。提到的软件算法与我的手算有何区别?更新: 原来在stackoverflow上已经有了类似的问题: 你可以在此处找到答案 Python CRC-32 woes 虽然这并不是非常直观。如果您想要一个更正式的描述,关于以太网帧的方法是如何完成的,请参考 Ethernet Standard document 802.3 Part 3 - Chapter 3.2.9 Frame Check Sequence Field
继续以上面的例子为例:
反转消息的位顺序。这表示它们将按位进入接收器的方式。
0x03
因此是0xC0
对消息的前32位进行补码。请注意,我们再次使用32位填充单个字节。
0xC000000000 xor 0xFFFFFFFF = 0x3FFFFFFF00
再次完成上述的异或和移位方法。大约进行6步后,您将得到:
0x13822f2d
上述的位序列然后被补码。
0x13822f2d xor 0xFFFFFFFF = 0xec7dd0d2
记住,我们在第一步中反转了位顺序,以获得以太网线上的表示。现在我们必须撤消这一步,最终实现我们的目标。
0x4b0bbe37
提出这种做法的人应该是 ...
很多时候,您实际上想知道接收的消息是否正确。为了实现这一点,您将接收到的消息(包括FCS)执行与以上1到5步相同的操作。结果应该是所谓的余数,它是给定多项式的常数。在本例中,它是 0xC704DD7B
。
正如 mcdowella 所提到的,您必须根据您使用的应用程序来调整比特,直到您正确地得到结果。
(0x104C11DB7 << 1)
- sebs