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

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

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

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

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

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

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

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

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

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

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

3 ответа

Решение

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

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

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

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

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

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

>>> hex(zlib.crc32('hello-world')% 2**32))                          
'0xb1d4025b'
Другие вопросы по тегам