python - 在 Python 中计算/验证 bz2 (bzip2) CRC32

标签 python c crc crc32 bzip2

我正在尝试计算/验证压缩的 bzip2 存档的 CRC32 校验和。

.magic:16                       = 'BZ' signature/magic number
.version:8                      = 'h' for Bzip2 ('H'uffman coding)
.hundred_k_blocksize:8          = '1'..'9' block-size 100 kB-900 kB

.compressed_magic:48            = 0x314159265359 (BCD (pi))
.crc:32                         = checksum for this block
...
... 
.eos_magic:48                   = 0x177245385090 (BCD sqrt(pi))
.crc:32                         = checksum for whole stream
.padding:0..7                   = align to whole byte

http://en.wikipedia.org/wiki/Bzip2

所以我知道 CRC 校验和在 bz2 文件中的位置,但我将如何验证它们。我应该binascii.crc32() 哪些 block 来获得两个 CRC?我已尝试逐字节计算各种 block 的 CRC,但未能找到匹配项。

谢谢。我将研究 bzip2 源代码和 bz2 Python 库代码,也许能找到一些东西,尤其是在 decompress() 方法中。

更新 1:

据我所知,区 block 头由以下标签标识。 但微小的 bz2 文件不包含 ENDMARK 文件。(感谢 adw,我们发现应该寻找 ENDMARK 的位移值,因为压缩数据未填充到字节。)

#define BLOCK_HEADER_HI  0x00003141UL
#define BLOCK_HEADER_LO  0x59265359UL

#define BLOCK_ENDMARK_HI 0x00001772UL
#define BLOCK_ENDMARK_LO 0x45385090UL

这来自 bzlib2recover.c 源代码, block 似乎总是从第 80 位开始,就在 CRC 校验和之前,应该从 CRC 计算中省略,因为不能对其进行 CRC 校验自己的 CRC 是相同的 CRC(你明白我的意思)。

searching for block boundaries ...
block 1 runs from 80 to 1182

查看计算这个的代码。

更新 2:

bzlib2recover.c 没有CRC计算功能,它只是从损坏的文件中复制CRC。但是,我确实设法在 Python 中复制了 block 计算器功能,以在 bz2 压缩文件中标出每个 block 的起始位和结束位。回到正轨,我发现 compress.c 引用了 bzlib_private.h 中的一些定义。

#define BZ_INITIALISE_CRC(crcVar) crcVar = 0xffffffffL;
#define BZ_FINALISE_CRC(crcVar) crcVar = ~(crcVar);
#define BZ_UPDATE_CRC(crcVar,cha)              \
{                                              \
   crcVar = (crcVar << 8) ^                    \
            BZ2_crc32Table[(crcVar >> 24) ^    \
                           ((UChar)cha)];      \
}

这些定义也被 bzlib.c 访问,s->blockCRCbzlib.c 中初始化和更新,并在中完成压缩.c。有 2000 多行 C 代码,这将需要一些时间来查看并弄清楚哪些进入了哪些没有。我也在问题中添加了 C 标签。

顺便说一下,这里是 bzip2 的 C 源代码 http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz

更新 3:

原来 bzlib2 block CRC32 是使用以下算法计算的:

dataIn是要编码的数据。

crcVar = 0xffffffff # Init
    for cha in list(dataIn):
        crcVar = crcVar & 0xffffffff # Unsigned
        crcVar = ((crcVar << 8) ^ (BZ2_crc32Table[(crcVar >> 24) ^ (ord(cha))]))

    return hex(~crcVar & 0xffffffff)[2:-1].upper()

其中BZ2_crc32Table定义在crctable.c

对于 dataIn = "justatest",返回的 CRC 是 7948C8CB,用该数据压缩了一个文本文件,bz2 文件中的 crc:32 校验和是 79 48 c8 cb 这是一场比赛。

结论:

bzlib2 CRC32 是(引用 crctable.c)

Vaguely derived from code by Rob Warnock, in Section 51 of the comp.compression FAQ...

...因此,据我所知,无法使用标准 CRC32 校验和计算器进行预先计算/验证,而是需要 bz2lib 实现(bzlib_private.h 中的第 155-172 行)。

最佳答案

以下是bzip2使用的CRC算法,用Python编写:

crcVar = 0xffffffff # Init
    for cha in list(dataIn):
        crcVar = crcVar & 0xffffffff # Unsigned
        crcVar = ((crcVar << 8) ^ (BZ2_crc32Table[(crcVar >> 24) ^ (ord(cha))]))

    return hex(~crcVar & 0xffffffff)[2:-1].upper()

(C 代码定义可以在 bzlib_private.h 的第 155-172 行找到)

BZ2_crc32Table 数组/列表可以在 bzip2 源代码的 crctable.c 中找到。此 CRC 校验和算法引用:“..模糊地从 Rob Warnock 的代码中导出,在 comp.compression FAQ 的第 51 节中......”(crctable.c )

校验和是根据未压缩的数据计算的。

资源可以在这里下载:http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz

关于python - 在 Python 中计算/验证 bz2 (bzip2) CRC32,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4468605/

相关文章:

python - 使用 Prototype 和 Django 的 Ajax 自动完成功能

arrays - 当 (void *) p == (void *) *p - 标准对此有何评论?

c - C 的最终 CRC

java - crc 四个字节将 C 代码转换为 Java 产生意外结果

python将列表写入文本文件导致长度不同

python - 谷歌应用引擎 : alternate method of get_by_id()

python - 从 pandas 列表中制作元组

c - 通过汇编查找数组的维度

java - 不同平台之间的数据传输协议(protocol)

ios - Swift 十六进制到字节 (iOS)