Python CRC-32 问题
Posted
技术标签:
【中文标题】Python CRC-32 问题【英文标题】:Python CRC-32 woes 【发布时间】:2011-06-30 04:03:47 【问题描述】:我正在编写一个 Python 程序来从 6 GB bz2 文件的中间提取数据。 bzip2 文件由可独立解密的数据块组成,因此我只需要找到一个块(它们由魔术位分隔),然后在内存中从中创建一个临时的单块 bzip2 文件,最后将其传递给bz2.decompress 函数。很简单,不是吗?
bzip2 format 末尾有一个文件的 crc32 校验和。没问题,binascii.crc32 来救援。可是等等。要校验和的数据不一定以字节边界结束,crc32函数对整数字节进行操作。
我的计划:对除最后一个字节之外的所有字节使用 binascii.crc32 函数,然后使用我自己的函数用最后 1-7 位更新计算出的 crc。但是几个小时的编码和测试让我一头雾水,我的疑惑可以归结为这个问题:crc32("\x00") 怎么不是0x00000000?根据***的文章,不应该吗?
您从 0b00000000 开始并用 32 个 0 填充,然后用 0x04C11DB7 进行多项式除法,直到前 8 位中没有剩余,即立即。你的最后 32 位是校验和,怎么可能不全为零?
我在 Google 上搜索了答案并查看了几个 CRC-32 实现的代码,但没有找到任何线索来解释为什么会这样。
【问题讨论】:
这有帮助吗:***.com/questions/4468605/… 不直接,不,因为这处理块校验和而不是文件校验和的结尾。但是问题、更新和答案很有趣,很有启发性,所以谢谢! 【参考方案1】:crc32("\x00") 怎么不是0x00000000?
基本的 CRC 算法是将输入消息视为 GF(2) 中的多项式,除以固定的 CRC 多项式,并使用多项式余数作为结果哈希。
CRC-32 对基本算法做了一些修改:
-
消息的每个字节中的位被反转。例如,字节 0x01 被视为多项式 x^7,而不是多项式 x^0。
消息右侧用 32 个零填充。
此反转和填充消息的前 4 个字节与 0xFFFFFFFF 进行异或运算。
取反余数多项式。
余数多项式与 0xFFFFFFFF 进行异或运算。
请记住,CRC-32 多项式的非反转形式是 0x104C11DB7。
让我们算出一字节字符串 0x00 的 CRC-32:
-
消息:0x00
反转:0x00
填充:0x00 00 00 00 00
异或:0xFF FF FF FF 00
除以 0x104C11DB7 时的余数:0x4E 08 BF B4
异或:0xB1 F7 40 4B
反转:0xD2 02 EF 8D
你知道了:0x00 的 CRC-32 是 0xD202EF8D。 (您应该验证这一点。)
【讨论】:
你能更好地解释第 5 步的结果吗? 0xFFFFFFFF00 % 0x104C11DB7 不会导致 0x4E08BFB4。我也不知道如何通过任何字节反转来获得它。 它是 en.wikipedia.org/wiki/Polynomial_long_division 。每个位代表一个单项式的系数。【参考方案2】:除了 one-shot decompress
函数之外,bz2 模块还包含一个类 BZ2Decompressor
,它在将数据馈送到 decompress 方法时对其进行解压缩。因此,它不关心文件结束校验和,并在到达块末尾时提供所需的数据。
为了说明,假设我已经找到了我希望从文件中提取的块并将其存储在 bitarray.bitarray 实例中(其他位旋转模块可能也可以工作)。然后这个函数会解码它:
def bunzip2_block(block):
from bz2 import BZ2Decompressor
from bitarray import bitarray
dummy_file = bitarray(endian="big")
dummy_file.frombytes("BZh9")
dummy_file += block
decompressor = BZ2Decompressor()
return decompressor.decompress(dummy_file.tobytes())
请注意,bitarray 的 frombytes
和 tobytes
方法以前称为 fromstring
和 tostring
。
【讨论】:
以上是关于Python CRC-32 问题的主要内容,如果未能解决你的问题,请参考以下文章