Вычислить / проверить bz2 (bzip2) CRC32 в Python - PullRequest
6 голосов
/ 17 декабря 2010

Я пытаюсь вычислить / проверить контрольные суммы CRC32 для сжатых архивов bzip2.

.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->blockCRC инициализируется и обновляется вbzlib.c и завершено в compress.c.Там более 2000 строк кода на C, на что потребуется некоторое время, чтобы просмотреть и выяснить, что входит, а что нет.Я также добавляю к вопросу тег C.

Кстати, вот источники C для bzip2 http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz

Обновление 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()

Где BZ2_crc32Table определен вcrctable.c

Для dataIn = "justatest" возвращается CRC 7948C8CB, после сжатия текстового файла с этими данными контрольная сумма crc: 32 внутри файла bz2 равна 79 48 c8 cb, что соответствует.

Вывод:

bzlib2 CRC32 (цитируя crctable.c)

Приблизительно получен из кода Роба Уорнока, в разделе 51 комп.FAQ по сжатию ...

... поэтому, насколько я понимаю, не может быть предварительно рассчитан / проверен с использованием стандартных калькуляторов контрольной суммы CRC32, а скорее требуется реализация bz2lib (строки 155-172 вbzlib_private.h).

1 Ответ

2 голосов
/ 21 декабря 2010

Ниже приведен алгоритм CRC, используемый bzip2, написанный на 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 можно найти в строках 155-172 в bzlib_private.h)

BZ2_crc32Table массив / список можно найти в crctable.c из исходного кода bzip2. Этот алгоритм контрольной суммы CRC цитирует: ".. неопределенно получен из кода Роба Уорнока в Разделе 51 FAQ по comp.compression ..." (crctable.c)

Контрольные суммы рассчитываются по несжатым данным .

Источники можно скачать здесь: http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz

...