如何用 Python 计算 CRC32 以匹配在线结果?

Posted

技术标签:

【中文标题】如何用 Python 计算 CRC32 以匹配在线结果?【英文标题】:How to calculate CRC32 with Python to match online results? 【发布时间】:2015-07-17 12:06:00 【问题描述】:

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

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

另一种方法,

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

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

http://www.lammertbies.nl/comm/info/crc-calculation.html http://crc32-checksum.waraxe.us/ http://www.md5calc.com/(从下拉列表中选择 CRC32B)

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

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

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

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

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

【问题讨论】:

@Yeo:hello-world 的正确 CRC32 是 0xb1d4025b 作为无符号整数,-0x4e2bfda5 作为有符号整数。他显然不知道这两个值是如何相关的,因此提出了这个问题。 【参考方案1】:

Python 2(与 py3 不同)正在执行带符号的 32 位 CRC。

那些网站正在执行无符号 32 位 CRC。

其他的值是一样的,从这里可以看出:

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

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

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

或者,十六进制:

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

&amp; 0xFFFFFFFF% 0x100000000&amp; (2**32-1)% (2**32) 等都是执行相同位旋转的等效方式;它只是归结为您认为最易读的一个。


* 这仅适用于执行整数除法的语言,例如 Python (-3 // 2 == -2);在执行截断整数除法的语言中,如 Java (-3 / 2 == -1),你仍然会得到一个负数。在甚至不需要除法和 mod 正确组合的语言中,比如 C,所有的赌注都没有了——但在 C 中,你只需将字节转换为你想要的类型......

【讨论】:

Python is doing a signed 32-bit CRC 请注意:在 Python3 中,这已更改为运行无符号 CRC。请参阅docs。 这不取决于如何进行除法,而是%的定义。在大多数语言中,它被定义为以下之一:x % y == x - floor(x / y) * y(“与除数相同的符号”,Python 所做的。如此积极,因为2**32 是正数)、x % y == x - truncate(x / y) * y(“与除数相同的符号”)或@ 987654337@(“正模”)。通常这与 / 相同,但并非总是如此。要在其他语言中始终使用正整数除法,您可以执行以下操作:def positive_mod(a, b): return ((a % b) + b) % b。见en.wikipedia.org/wiki/Modulo_operation【参考方案2】:

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

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

结果如预期的那样是0xb1d4025b

【讨论】:

我很好奇为什么跨平台会有所不同。 Python 的行为不是一刀切吗? (忽略 2.x 和 3.x 的差异) @chronodekar:我相信在源代码中找到它不会太难;如果您自己找不到,您可以创建一个新问题。但是从快速测试来看,它在 Mac 2.7 和 Linux 2.7 上是负面的,在 Windows 2.7 和 Mac 3.5 上是正面的,所以我很确定这是一个平台问题,而不是 2-vs.-3 问题。或者也许是两者的结合。 (无论如何,它对 OP 没有帮助,它的 Python 显然确实签署了 crc32,就像我的 Mac 2.7 一样......) @chronodekar 我在 Python 文档中没有找到任何明确的答案,所以我编辑了我的答案以在所有 Python 版本和平台上具有相同的行为。 请注意,Python 3 保证 binascii.crc32 返回无符号值,而 2.6 和 2.7 应保证有符号值,因此平台差异不应影响这一点。【参考方案3】:

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

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

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

【讨论】:

以上是关于如何用 Python 计算 CRC32 以匹配在线结果?的主要内容,如果未能解决你的问题,请参考以下文章

python 通过crc32得到加密文件内容

Python中的CRC32计算而不使用库

Python中无需解压即可计算zip内容的CRC32、MD5和SHA1

CRC32C 的测试向量

python 计算CRC32

关于python实现CRC32Mpeg2的应用和总结