Как рассчитать CRC32 с Python, чтобы соответствовать онлайн-результатам?
Я пытаюсь вычислить / сгенерировать хэш CRC32 некоторых случайных строк, используя Python, но они не соответствуют значениям, которые я генерирую из онлайн-источников. Вот что я делаю на своем компьютере,
>>> 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'
К сожалению, это тоже не помогло.:(
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'