Ruby pack('H*') equivalent in Python

634 Views Asked by At

I'm having a hard time figuring out why outputs aren't the same. Notice that the difference is very tiny if you compare both OUT's. What I'm trying to achieve is have the same output in Python to the one in Ruby.

Ruby:

IN:['034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192'].pack('H*')

OUT:\x03AQ\xA3\xECF\xB5g\nh+\nc9O\x865\x87\xD1\xBC\x97H;\elp\xEBX\xE7\xF0\xAE\xD1\x92

Python:

IN:unhexlify('034151a3ec46b5670a682b0a63394f863587d1bc97483b1b6c70eb58e7f0aed192') OUT:\x03AQ\xa3\xecF\xb5g\nh+\nc9O\x865\x87\xd1\xbc\x97H;\x1blp\xebX\xe7\xf0\xae\xd1\x92

2

There are 2 best solutions below

0
On BEST ANSWER

Both languages have produced the same sequence of bytes; the only difference is in the way they display those bytes to you. Ruby has an \e string escape sequence for the 1b byte (ASCII ESC, escape), while Python displays that byte as \x1b.

0
On

I understand that this question is very old, but I had the exact same trouble where a ruby 'pack'ed sha1 was being stored to a mongodb field, and trying to read it in using the pymongo find function produced something that seemed unreadable at first.

I solved it not using hexlify, but just using the binascii binary to ascii decoder (which itself still generates a 28-byte long binary), and then using base64 decode and traditional hexing:

new_sha1= base64.b64decode(binascii.b2a_base64(agg_sha1, newline=False)).hex()

I double-checked that it generated the correct sha1 by searching in the mongo shell afterwards. Finding the answer was a miracle, and I hope this helps someone else demystify 'pack'.

Edited to add - found out binascii can do even better with the b2a_hex function!

new_sha1= binascii.b2a_hex(sha1)

So as long as you're using .pack('H*') this should work