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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30092226/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 07:56:48  来源:igfitidea点击:

How to calculate CRC32 with Python to match online results?

pythoncrc32

提问by chronodekar

I'm trying to calculate/generate the CRC32 hash of some random strings using Python but they do not match the values I generate from online sources. Here is what I'm doing on my PC,

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

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

Another approach,

另一种做法,

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

The fact that the above results are identical tells me that I'm calling the function correctly. But, if I go to the following online sources,

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

For the string "hello-world" they all give the same value = b1d4025b

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

Does anyone know what I need to do, to get matching results?

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

As I was typing this question it occurred to me that I might need to convert my Python result to hex,

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

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

Unfortunately, that hasn't helped either. :(

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

采纳答案by abarnert

Python 2 (unlike py3) is doing a signed 32-bit CRC.

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

Those sites are doing an unsigned 32-bit CRC.

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

The values are the same otherwise, as you can see from this:

否则,这些值是相同的,如您所见:

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

One quick way to convert from 32-bit signed to 32-bit unsigned is:*

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

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

Or, in hex:

或者,在十六进制中:

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

& 0xFFFFFFFFor % 0x100000000or & (2**32-1)or % (2**32)and so on are all equivalent ways to do the same bit-twiddling; it just comes down to which one you find most readable.

& 0xFFFFFFFFor% 0x100000000& (2**32-1)or% (2**32)等等都是进行相同位操作的等效方法;它只是归结为您认为最易读的一个。



* This only works in languages that do floored integer division, like Python (-3 // 2 == -2); in languages that do truncated integer division, like Java (-3 / 2 == -1), you'll still end up with a negative number. And in languages that don't even require that division and mod go together properly, like C, all bets are off—but in C, you'd just cast the bytes to the type you want…

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

回答by Alexey

zlib.crc32 documentationsuggests using the following approach "to generate the same numeric value across all Python versions and platforms".

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

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

The result is 0xb1d4025bas expected.

结果0xb1d4025b如预期。

回答by chw21

It seems that python is returning an signed integer (hence the negative number), whereas the others are returning an unsigned integer.

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

I have tried using a modulus with 2^32, and it gave the same value as these sites.

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

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