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

时间:2010-12-17 07:43:35

标签: 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()获得两个CRC的块?我已经尝试逐字节地计算各种块的CRC,但还没有设法得到匹配。

谢谢。我将查看bzip2源代码和bz2 Python库代码,以便找到一些东西,特别是在decompress()方法中。

更新1:

就我所见,块标题由以下标记标识。 但微小的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源,块似乎始终在第80位,就在CRC校验和之前,这应该从CRC计算中省略,因为不能将CRC自己的CRC校准为相同的CRC(你明白我的意思)。

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

查看计算此代码的代码。

更新2:

bzlib2recover.c没有CRC计算功能,它只是从受损文件中复制CRC。但是,我确实设法在Python中复制块计算器功能,以标记bz2压缩文件中每个块的起始位和结束位。回到正轨,我发现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中初始化和更新,并在compress.c中完成。有超过2000行的C代码,需要一些时间来查看并找出进入和不进的内容。我也在问题中添加C标记。

顺便说一句,这里是bzip2 http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz

的C源代码

更新3:

结果bzlib2块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()

crctable.c

中定义了BZ2_crc32Table

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

结论:

bzlib2 CRC32是(引用crctable.c

  

隐约来自Rob的代码   Warnock,在第51节   comp.compression FAQ ...

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

1 个答案:

答案 0 :(得分:2)

以下是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源代码的crctable.c中找到

bzip2数组/列表。这个CRC校验和算法引用:“..模糊地从Rob Warnock的代码中导出,在comp.compression FAQ的第51节......”crctable.c

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

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