Как вычислить CRC32 с Python для соответствия онлайн-результатам?

Я пытаюсь вычислить/сгенерировать хэш CRC32 некоторых случайных строк с использованием Python, но они не соответствуют значениям, которые я генерирую из онлайн-источников. Вот что я делаю на своем ПК,

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

Другой подход,

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

Тот факт, что приведенные выше результаты идентичны, говорит мне, что я правильно вызываю функцию. Но, если я перейду к следующим онлайн-источникам,

Для строки "hello-world" все они дают одинаковое value = b1d4025b

Кто-нибудь знает, что мне нужно сделать, чтобы получить соответствующие результаты?

Когда я вводил этот вопрос, мне пришло в голову, что мне может потребоваться преобразовать мой результат Python в hex,

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

К сожалению, это тоже не помогло.: (

Ответ 1

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 вы просто приводите байты к нужному типу...

Ответ 2

В документации zlib.crc32 предлагается использовать следующий подход "для генерации одинакового числового значения во всех версиях и платформах Python".

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

Результат 0xb1d4025b как и ожидалось.

Ответ 3

Кажется, что python возвращает целое число со знаком (отсюда и отрицательное число), тогда как остальные возвращают целое число без знака.

Я попытался использовать модуль с 2 ^ 32, и он дал такое же значение, как эти сайты.

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