使用Python正确计算CRC32

问题描述 投票:0回答:4

我正在尝试使用 Python 计算/生成一些随机字符串的 CRC32 哈希,但它们与我从在线源生成的值不匹配。这是我在电脑上所做的事情,

>>> import binascii
>>> binascii.crc32('hello-world')
-1311505829

另一种方法,

>>> import zlib
>>> zlib.crc32('hello-world')
-1311505829

以上结果相同的事实告诉我,我正确地调用了该函数。但是,如果我访问以下在线资源,

对于字符串“hello-world”,它们都给出相同的值= b1d4025b

有人知道我需要做什么才能获得匹配结果吗?

当我输入这个问题时,我突然想到我可能需要将 Python 结果转换为十六进制,

>>> hex(zlib.crc32('hello-world'))
'-0x4e2bfda5'

不幸的是,这也没有帮助。

python crc32
4个回答
56
投票

Python 2(与 py3 不同)正在执行签名的 32 位 CRC。

这些站点正在执行未签名的 32 位 CRC。

其他方面的值是相同的,您可以从中看到:

>>> 0x100000000 - 0xb1d4025b == 0x4e2bfda5
True

从 32 位有符号转换为 32 位无符号的一种快速方法是:*

>>> -1311505829 % (1<<32)
2983461467

或者,十六进制:

>>> hex(-1311505829 % (1<<32))
'0xb1d4025b'

& 0xFFFFFFFF
% 0x100000000
& (2**32-1)
% (2**32)
等等都是进行相同位操作的等效方法;这只是取决于您认为哪一篇最具可读性。


* 这只适用于进行整数除法的语言,例如 Python (

-3 // 2 == -2
);在进行截断整数除法的语言中,例如 Java (
-3 / 2 == -1
),您仍然会得到负数。在甚至不需要除法和取模正确结合在一起的语言中,比如 C,所有的赌注都没有——但在 C 中,你只需将字节转换为你想要的类型......


39
投票

zlib.crc32 文档建议使用以下方法“在所有 Python 版本和平台上生成相同的数值”。

import zlib
hex(zlib.crc32(b'hello-world') & 0xffffffff)

结果是

0xb1d4025b
,符合预期。

请注意,根据Python 3.10文档,

 & 0xffffffff
仅适用于Python 2或更早版本。


8
投票

Python 似乎返回一个有符号整数(因此是负数),而其他函数则返回一个无符号整数。

我尝试使用 2^32 的模数,它给出的值与这些网站相同。

>>> hex(zlib.crc32(b'hello-world')% 2**32)
'0xb1d4025b'

0
投票

也可以通过

binascii.crc32

import binascii

crc: int = binascii.crc32('asdf'.encode())

# Format to fixed-length hex string (8 characters)
fixed_length_hex: str = f'{crc32_value:08x}'

示例:

print(f'{binascii.crc32(b'hello-world'):08x}')

b1d4025b

根据文档,使用 Python 3,crc32 结果始终是无符号的,因此无需执行

& 0xffffffff

© www.soinside.com 2019 - 2024. All rights reserved.