python - Necesita ayuda para descomprimir los datos zlib almacenados en el código de barras azteca(Deutsche Bahn Ticket)
parsing barcode (1)
Premisa
Intento descifrar los datos del formato de código de barras utilizado actualmente en los boletos emitidos por Deutsche Bahn (ferrocarril alemán). He encontrado este sitio web muy útil (alemán) que ya hace algo similar y ofrece un script de python .
El sitio web indica que los datos se comprimen con zlib
, el blob resultante se firma con DSA y todo se almacena en el código de barras (formato azteca). Ejemplo de tal código de barras
Problema
He utilizado el script proporcionado en el sitio web para decodificar con éxito un ticket. Instaló la biblioteca python-pyasn1. Lea el código de barras (utilizó BCTester según las instrucciones, tuvo algunos problemas con la aplicación NeoReader) y convirtió el resultado en hexadecimal. Guardado los datos hexadecimales como archivo de texto sin formato (como por alguna razón es requerido por el guión) y analizado el archivo con el guión. Funcionó.
Pero el script está haciendo demasiado. Me gustaría hacer el análisis yo mismo, pero no puedo hacer funcionar la descompresión zlib y entiendo muy poco del código para darle sentido. Sé casi que no hay Python. Tengo algo de experiencia en programación, sin embargo.
Si simplemente mira los datos del código de barras, se ve así: https://gist.github.com/oelna/096787dc18596aaa4f5f
La primera pregunta sería: ¿Cuál es la firma de DSA y necesito dividirla primero entre los datos comprimidos?
El segundo: ¿Cómo podría ser un simple script de Python que lee el blob de código de barras de un archivo y simplemente lo descomprime, para que yo pueda analizar el formato. Tenía algo en mente como
#!/usr/bin python
import zlib
ticket = open(''ticketdata.txt'').read()
print zlib.decompress(ticket)
pero no está funcionando. Cualquier sugerencia en la dirección correcta sería apreciada.
Aquí están los datos hexadecimales que el script puede leer si se guardan en un archivo:
23 55 54 30 31 30 30 38 30 30 30 30 30 31 30 2c 02 14 1c 3d e9 2d cd 5e c4 c0 56 bd ae 61 3e 54 ad a1 b3 26 33 d2 02 14 40 75 03 d0 cf 9c c1 f5 70 58 bd 59 50 a7 af c5 eb 0a f4 74 00 00 00 00 30 32 37 31 78 9c 65 50 cb 4e c3 30 10 e4 53 2c 71 43 4a d9 f5 2b 36 b7 84 04 52 01 55 51 40 1c 51 01 23 2a 42 0e 21 15 3f c7 8d 1f 63 36 11 52 2b 7c f1 78 76 76 66 bd f7 8f 4d 5d 54 c4 44 ce 10 05 d2 eb 78 5b ac 32 7b b4 77 c8 11 6b 62 c7 d6 79 aa ea aa 16 e1 b2 22 4d c4 01 ad 36 58 61 ca 6b 30 c6 e5 64 a0 b6 97 0f a6 a9 6f d6 71 df c7 cf 3e 7f 37 93 66 8e c6 71 de 92 4c c0 e1 22 0d fd 57 7a cb ee b6 cf ef 69 54 fd 66 44 05 31 d0 03 18 01 05 40 04 70 9c 51 46 ad 38 49 33 00 86 20 dd 42 88 04 22 5f a6 a1 db f6 78 79 d4 79 95 76 1f 3f df fd e7 98 86 16 b1 30 0b 65 d6 3c bd 2a 15 ce d8 ab e5 79 9d 47 7b da 34 13 c7 34 73 5a 6b 0b 35 72 d9 5c 0d bb ae 53 aa e8 5f 86 b4 01 e9 25 8d 0d 50 8e 72 3c 39 3c b2 13 94 82 74 ce 2d c7 b3 41 8b ed 4c 9f f5 0b e2 85 6c 01 8c fe c7 b8 e9 87 8c d9 f1 90 28 a3 73 fe 05 6d de 5f f1
Actualización / Solución:
La sugerencia de Mark Adler me puso en el camino correcto. Me tomó horas, pero logré una solución funcional para este problema en particular. Si hubiera sido más inteligente, habría reconocido el encabezado zlib 78 9C
en el desplazamiento 68. Simplemente dividir los datos en este punto y la segunda mitad se descomprime sin quejarse. Se advirtió, muy triste python
dsa_signature = ''''
zlib_data = ''''
cursor = 0
with open(''ticketdata.txt'', "rb") as fp:
chunk = fp.read(1)
while chunk:
if(cursor < 68):
dsa_signature += chunk
else:
zlib_data += chunk
chunk = fp.read(1)
cursor = cursor + 1
print "/nSignature:"
print "%s/n" % dsa_signature
print "/nCompressed data:"
print "%s/n" % zlib_data
print "/nDecoded:"
print zlib.decompress(zlib_data)
Si hay una solución fácil para esto, no dude en comentar. Continuaré trabajando en esto un poco más e intentaré que sea una solución más robusta que busque activamente el encabezado zlib, sin tener que codificar el offset. La primera mitad es un código identificador, como #UT010080000060,
seguido de una firma ASN.1
DSA, que afortunadamente no necesito verificar ni modificar.
Hay una secuencia de zlib completa y válida que comienza en el desplazamiento 68 en sus datos hexadecimales y va hasta el final. Se descomprime a:
U_HEAD01005300802P9QAN-40501201514560DEDE0080ID0200180104840080BL020357031204GW3HEMP906012015060120151021193517S0010018Fernweh-Ticket natS00200012S0030001AS00900051-0-0S01200010S0140002S2S0150006BerlinS0160011NeumünsterS0210038B-Hbf 08:16 ICE794 / HH-Hbf 10:16 IC2224S0230013Krull AndreaS026000213S0270019 *************** 0484S0280013Andrea # Krull S031001006.01.2015S032001006.01.2015S035000511160S0360003271
Si suelta los primeros 68 bytes de su ejemplo, zlib.decompress()
devolverá lo anterior.
Depende de usted averiguar cuáles son los primeros 68 bytes.