Вычислить / проверить bz2 (bzip2) CRC32 в Python

Я пытаюсь вычислить / проверить контрольные суммы 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 по comp.compression ...

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


person soulseekah    schedule 17.12.2010    source источник
comment
bzip2 использует 32-битный стандарт CRC AUTODIN-II, Ethernet и FDDI   -  person soulseekah    schedule 17.12.2010
comment
Разве CRC не относится к несжатым данным, содержащимся в этом блоке?   -  person psmears    schedule 17.12.2010
comment
Первое, что я попробовал, - это вычислить CRC для простых несжатых данных. Но не совпадет. Данные представляли собой простой hello в текстовом файле. Я пробовал разные онлайн-калькуляторы CRC32 и библиотечные, которые у меня есть. Либо мне очень не везет, либо я что-то не так делаю.   -  person soulseekah    schedule 17.12.2010
comment
Тег open("test.txt.bz2","wb").write(bz2.compress("hello")) CRC32 указывает, что CRC32 для блока 19 31 65 3d, тогда как hex(crc32("hello")) (из binascii) возвращает 36 10 a6 86   -  person soulseekah    schedule 17.12.2010
comment
Я полагаю, что CRC32 - это CRC32 сжатых блоков.   -  person Xavier Combelle    schedule 17.12.2010
comment
Но крошечные файлы bz2 не содержат файлов ENDMARK. -- Они делают; блоки не дополняются байтами, поэтому вам также придется искать версии магических значений с битовым сдвигом.   -  person adw    schedule 17.12.2010
comment
@Soulseekah Поскольку вы отредактировали заголовок, добавив в него «[РЕШЕНО]», можете ли вы опубликовать ответ со своими выводами и (при желании) отметить его как ответ, который вы искали?   -  person spade78    schedule 21.12.2010
comment
@ spade78 спасибо за подсказку, готово.   -  person soulseekah    schedule 21.12.2010


Ответы (2)


Ниже приводится алгоритм 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 часто задаваемых вопросов о сжатии ..." (crctable.c)

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

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

person soulseekah    schedule 21.12.2010
comment
Вот реализация bzlib2 CRC в Java zetagrid .net / zeta / doc / src / org / apache / tools / bzip2 / CRC.java.html. - person soulseekah; 22.12.2010

Чтобы добавить к существующему ответу, в конце потока есть окончательная контрольная сумма (та, которая стоит после eos_magic). Она функционирует как контрольная сумма для всех контрольных сумм отдельных блоков Хаффмана. Он инициализируется нулем. Он обновляется каждый раз, когда вы заканчиваете проверку существующей контрольной суммы блока Хаффмана. Чтобы обновить его, сделайте следующее:

crc: u32 = # latest validated Huffman block CRC
ccrc: u32 = # current combined checksum

ccrc = (ccrc << 1) | (ccrc >> 31);
ccrc ^= crc;

В конце сверьте значение ccrc с 32-битным значением без знака, которое вы читаете из сжатого файла.

person Gaurang Tandon    schedule 15.01.2021