如何在Python中解包二进制十六进制格式数据?

7 投票
3 回答
29514 浏览
提问于 2025-04-11 09:34

我使用PHP的 pack() 函数把一个字符串转换成了二进制的十六进制表示。

$string = md5(time); // 32 character length
$packed = pack('H*', $string);

这里的 H* 格式表示“十六进制字符串,先高位后低位”。

如果要在PHP中解包这个数据,我只需要用 unpack() 函数,并且使用 H* 格式标志。

那么在Python中,我该如何解包这些数据呢?

3 个回答

8

在Python中,你可以使用 struct 模块来实现这个功能。

>>> from struct import *
>>> pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('hhl')
8

希望这对你有帮助。

11

对于 struct.pack 来说,没有对应的“十六进制半字节”代码,所以你需要先手动将数据打包成字节,像这样:

hex_string = 'abcdef12'

hexdigits = [int(x, 16) for x in hex_string]
data = ''.join(struct.pack('B', (high <<4) + low) 
               for high, low in zip(hexdigits[::2], hexdigits[1::2]))

或者更简单的方法是直接使用十六进制编码。也就是说:

>>> data = hex_string.decode('hex')
>>> data
'\xab\xcd\xef\x12'

要解包,你可以用类似的方法把结果再编码成十六进制

>>> data.encode('hex')
'abcdef12'

不过要注意,对于你的例子来说,其实在编码时根本不需要经过十六进制的转换。直接使用 md5 的二进制摘要就可以了。也就是说:

>>> x = md5.md5('some string')
>>> x.digest()
'Z\xc7I\xfb\xee\xc96\x07\xfc(\xd6f\xbe\x85\xe7:'

这和你之前打包的表示是一样的。要得到十六进制的表示,可以使用上面提到的解包方法:

>>> x.digest().decode('hex')
'acbd18db4cc2f85cedef654fccc4a4d8'
>>> x.hexdigest()
'acbd18db4cc2f85cedef654fccc4a4d8'

[编辑]:更新为使用更好的方法(十六进制编码)

13

有一种简单的方法可以使用 binascii 模块来实现:

>>> import binascii
>>> print binascii.hexlify("ABCZ")
'4142435a'
>>> print binascii.unhexlify("4142435a")
'ABCZ'

除非我对半字节的顺序理解错了(默认是高半字节在前……其他的顺序真是让人难以理解),这样的方法应该是完全足够的!

此外,Python 的 hashlib.md5 对象有一个 hexdigest() 方法,可以自动将 MD5 摘要转换成 ASCII 十六进制字符串,所以对于 MD5 摘要来说,这个方法其实并不是必须的。希望这对你有帮助。

撰写回答