我正在尝试逐字节计算以太网数据包的帧校验序列(FCS).多项式是0x104C11DB7.我确实遵循了这里所见的XOR-SHIFT算法http://en.wikipedia.org/wiki/Cyclic_redundancy_check或http://www.woodmann.com/fravia/crctut1.htm
假设假定具有CRC的信息仅为一个字节.假设它是0x03.
步骤:向右打32位
0x0300000000
将多项式和左侧的数据与它们的第一个非零和xor对齐
0x300000000 xor 0x209823B6E = 0x109823b6e
取余数对齐和xor
0x109823b6e xor 0x104C11DB7 = 0x0d4326d9
由于没有剩下的位,0x03的CRC32应该是 0x0d4326d9
不幸的是,所有的软件实现都告诉我我错了,但是我做错了什么或者他们做了什么不同的事情?
Python告诉我:
"0x%08x" % binascii.crc32(chr(0x03))
0x4b0bbe37
Run Code Online (Sandbox Code Playgroud)
这里的在线工具http://www.lammertbies.nl/comm/info/crc-calculation.html#intr获得了相同的结果.我的手计算与上述软件使用的算法有什么区别?
更新:
事实证明堆栈溢出已经存在类似的问题:
你在这里找到一个答案Python CRC-32的问题
虽然这不是很直观.如果您想要更正式地描述如何为以太网帧完成,您可以查看以太网标准文档802.3第3部分 - 第3.2.9章帧校验序列字段
让我们继续上面的例子:
反转邮件的位顺序.这代表了他们逐点进入接收器的方式.
0x03 因此是 0xC0
补充邮件的前32位.请注意,我们再次使用32位填充单个字节.
0xC000000000 xor 0xFFFFFFFF = 0x3FFFFFFF00
再次完成上面的Xor和shift方法.大约6步之后你得到:
0x13822f2d
然后补充上述比特序列.
0x13822f2d xor 0xFFFFFFFF = 0xec7dd0d2
请记住,我们颠倒了位顺序,以便在第一步中获得以太网线上的表示.现在我们必须扭转这一步,我们终于完成了我们的任务.
0x4b0bbe37
想出这种做法的人应该......
很多时候你真的想知道你收到的信息是正确的.为了达到这个目的,您可以收到包括FCS在内的收到的消息,并执行与上述相同的步骤1到5.结果应该是他们所谓的残留物.这是给定多项式的常数.在这种情况下它是0xC704DD7B.
正如mcdowella所提到的那样,你必须玩弄你的位,直到你做对了,这取决于你正在使用的应用程序.
我正在编写一个Python程序,用于从6 GB bz2文件的中间提取数据.bzip2文件由独立可解密的数据块组成,所以我只需要找到一个块(它们由魔术位分隔),然后在内存中创建一个临时的一块bzip2文件,最后将其传递给bz2.decompress函数.容易,不是吗?
bzip2 格式最后有一个文件的crc32校验和.没问题,binascii.crc32来救援.可是等等.要校验和的数据不一定以字节边界结束,而crc32函数在整数个字节上运行.
我的计划:在除最后一个字节之外的所有字节上使用binascii.crc32函数,然后使用我自己的函数来更新最后1-7位的计算crc.但是数小时的编码和测试让我感到困惑,我的困惑可以归结为这个问题:为什么crc32("\ x00")不是0x00000000?根据维基百科的文章,它应该不是吗?
你从0b00000000开始,用32 0填充,然后用0x04C11DB7进行多项式除法,直到前8位没有剩下的,这是立即的.你的最后32位是校验和,怎么能不是全零?
我搜索了Google的答案并查看了几个CRC-32实现的代码,却没有找到任何关于为什么会这样做的线索.