web-dev-qa-db-fra.com

Comment calculer CRC32 avec Python pour faire correspondre les résultats en ligne?

J'essaie de calculer/générer le hachage CRC32 de certaines chaînes aléatoires en utilisant Python mais elles ne correspondent pas aux valeurs que je génère à partir de sources en ligne. Voici ce que je fais sur mon PC,

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

Une autre approche,

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

Le fait que les résultats ci-dessus soient identiques me dit que j'appelle correctement la fonction. Mais, si je vais sur les sources en ligne suivantes,

Pour la chaîne "hello-world", ils donnent tous la même valeur = b1d4025b

Est-ce que quelqu'un sait ce que je dois faire pour obtenir des résultats correspondants?

Pendant que je tapais cette question, je me suis dit que je pourrais avoir besoin de convertir mon résultat Python en hex,

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

Malheureusement, cela n'a pas aidé non plus. :(

19
chronodekar

Python 2 (contrairement à py3) effectue un CRC 32 bits signé.

Ces sites effectuent un CRC 32 bits non signé.

Sinon, les valeurs sont les mêmes, comme vous pouvez le voir:

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

Une façon rapide de convertir de 32 bits signé en 32 bits non signé est:*

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

Ou, en hex:

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

& 0xFFFFFFFF Ou % 0x100000000 Ou & (2**32-1) ou % (2**32) et ainsi de suite sont tous des moyens équivalents pour faire le même bit-twiddling; il s'agit simplement de celui que vous trouvez le plus lisible.


* Cela ne fonctionne que dans les langages qui font une division entière plancher, comme Python (-3 // 2 == -2); Dans les langages qui font une division entière tronquée, comme Java = (-3 / 2 == -1), Vous vous retrouverez toujours avec un nombre négatif. Et dans les langues qui n'exigent même pas que la division et le mod fonctionnent correctement, comme C, tous les paris sont désactivés, mais en C, vous venez de transtyper les octets dans le type que vous voulez…

27
abarnert

documentation zlib.crc32 suggère d'utiliser l'approche suivante "pour générer la même valeur numérique sur toutes les Python").

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

Le résultat est 0xb1d4025b comme prévu.

15
Alexey

Il semble que python renvoie un entier signé (d'où le nombre négatif), tandis que les autres retournent un entier non signé.

J'ai essayé d'utiliser un module avec 2 ^ 32, et cela a donné la même valeur que ces sites.

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