2010-12-17 15 views
6

Estoy tratando de calcular/validar las sumas de comprobación CRC32 para los archivos comprimidos bzip2.Calcular/validar bz2 (bzip2) CRC32 en Python

.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

así que sé donde las sumas de comprobación CRC están en un archivo bz2, pero ¿cómo hago para validarlos. ¿Qué fragmentos debo binascii.crc32() para obtener ambos CRC? He intentado calcular el CRC de varios fragmentos, byte a byte, pero no he podido obtener una coincidencia.

Gracias. Buscaré en las fuentes bzip2 y en el código de la biblioteca Python bz2, tal vez para encontrar algo, especialmente en el método decompress().

Actualización 1:

El bloque de cabeceras se identifican por las siguientes etiquetas por lo que yo puedo ver. Pero los pequeños archivos bz2 no contienen los ENDMARK. (Gracias a adw, hemos descubierto que uno debe buscar bits valores de la ENDMARK cambiado, ya que los datos comprimidos no se rellena con bytes.)

#define BLOCK_HEADER_HI 0x00003141UL 
#define BLOCK_HEADER_LO 0x59265359UL 

#define BLOCK_ENDMARK_HI 0x00001772UL 
#define BLOCK_ENDMARK_LO 0x45385090UL 

Se trata de la fuente bzlib2recover.c, los bloques parecen comenzar siempre en el bit 80, justo antes de la suma de comprobación de CRC, que debe omitirse en el cálculo de CRC, ya que uno no puede CRC su propio CRC para ser el mismo CRC (obtiene mi punto).

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

Mirando el código que calcula esto.

Actualización 2:

bzlib2recover.c no tiene las funciones de cálculo CRC, simplemente copia el CRC de los archivos dañados. Sin embargo, logré replicar la funcionalidad de la calculadora de bloques en Python, para marcar los bits inicial y final de cada bloque en un archivo comprimido bz2. Volviendo a la pista, he encontrado que compress.c se refiere a algunas de las definiciones en 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)];  \ 
} 

Estas definiciones se accede por bzlib.c así, s->blockCRC se inicializa y se actualizan en bzlib.c y finalizados en compress.c. Hay más de 2000 líneas de código C, lo que tomará un tiempo para ver y descubrir qué entra y qué no. Estoy agregando la etiqueta C a la pregunta también.

Por cierto, aquí son las fuentes C para bzip2 http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz

Actualizar 3:

resulta bzlib2 bloque CRC32 se calcula utilizando el siguiente algoritmo:

dataIn es los datos a estar codificado

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() 

Dónde BZ2_crc32Table se define en crctable.c

Para dataIn = "justatest" la CRC devuelve es 7948C8CB, después de haber comprimido un archivo de texto con los datos, el CRC: 32 de suma de control dentro del archivo bz2 es 79 48 c8 cb que es un partido.

Conclusión:

bzlib2 CRC32 se (donde se cita crctable.c)

vagamente derivada de código por Rob Warnock, en la Sección 51 de la FAQ comp.compression ...

... por lo tanto, por lo que yo entiendo, no se puede precalcular/validar usando calculadoras de suma de comprobación estándar CRC32, pero r ather requiere la implementación bz2lib (líneas 155-172 en bzlib_private.h).

+0

'bzip2' utiliza el AUTODIN-II, Ethernet y FDDI CRC de 32 bits estándar – soulseekah

+0

no ¿El CRC se refiere a los datos no comprimidos que contienen este bloque? – psmears

+0

Lo primero que intenté fue calcular el CRC para los datos simples sin comprimir. Pero no coincidirá. La información era un simple 'hola' en un archivo de texto. Probé diferentes calculadoras CRC32 en línea y de biblioteca que tengo a mi disposición. O tengo mucha mala suerte o estoy haciendo algo mal. – soulseekah

Respuesta

2

El siguiente es el algoritmo CRC utilizado por bzip2, escrito en 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() 

(definiciones de los códigos C se pueden encontrar en las líneas 155-172 en bzlib_private.h)

BZ2_crc32Table matriz/lista se puede encontrado en crctable.c del código fuente bzip2. Este algoritmo de suma de comprobación CRC es, citando: "..vaguely derivada de código por Rob Warnock, en la Sección 51 de la FAQ comp.compression ..." (crctable.c)

Las sumas de comprobación se calculan sobre los datos sin comprimir .

Las fuentes se pueden descargar aquí: http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz

+0

Aquí está la implementación de CRC bzlib2 en Java http://www.zetagrid.net/zeta/doc/src/org/apache/tools/bzip2/CRC.java.html – soulseekah

Cuestiones relacionadas