2

我正在尝试将一些 Ruby 代码转换为 Python。我在这条线上遇到了麻烦:

Digest::MD5.digest(message).unpack('L*')

我想我应该使用struct模块和那个hashlib,但如果我这样做:

struct.unpack('L', hashlib.md5(message).digest())

我收到此错误:

struct.error: unpack requires a bytes object of length 4

我该怎么办?谢谢,

魔方

PS 输出应该是 4 x 32 位整数的列表:

irb(main):039:0> Digest::MD5.digest('Hash').unpack('L*')
=> [631892218, 1967199614, 3683860954, 4130231798]
4

3 回答 3

4

不支持任意长度的解包(*运算符)。您必须手动指定中继器。

幸运的是,struct 模块确实允许您指定固定长度,hashlib 模块会告诉您预期的字节数。通过在您指定应用模式的次数之前放置一个整数。L库中的特定散列hashlib具有一个.digest_size属性,可以告诉您特定散列的长度是多少字节。

结合这些:

structspec = '%iL' % (hashlib.hash('md5').digest_size / 4)
struct.unpack(structspec, hashlib.md5(message).digest())

如果你甚至不想在4那里硬编码,你也可以询问unsigned longstruct.calcsize的大小:L

structspec = '%iL' % (hashlib.hash('md5').digest_size / struct.calcsize('L'))
struct.unpack(structspec, hashlib.md5(message).digest())

In fact, on 64 bit platforms like my Mac, L is 8 bytes, so the latter calculation matters enormously if you are deploying across different architectures.

于 2012-07-12T08:21:25.650 回答
2

struct.unpack('L', ...)只会从参数中解压缩一个 long。您要做的是全部提取,与 Ruby 不同,Python 的解包函数无法解包任意数量的值,而是必须重复格式说明符。

hash = hashlib.md5(message).digest()
struct.unpack('L' * (len(hash) / 4), hash)

这将在字符串允许的范围内重复'L'多次并解压缩散列中的所有整数并返回一个包含 len / 4 个项目的元组。如果您希望将结果作为列表,只需将其转换为list().

于 2012-07-12T08:18:57.017 回答
1

If you're sure you want 4 longs, the format is 'LLLL':

struct.unpack('LLLL', hashlib.md5(message).digest())
于 2012-07-12T08:27:05.963 回答