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 的 frombytestobytes 方法以前称为 fromstringtostring

【讨论】:

以上是关于Python CRC-32 问题的主要内容,如果未能解决你的问题,请参考以下文章

Python中的CRC32计算而不使用库

如何用 Python 计算 CRC32 以匹配在线结果?

python crc32

Python中无需解压即可计算zip内容的CRC32、MD5和SHA1

Python_CRC32

关于python实现CRC32Mpeg2的应用和总结