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. :(
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…
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.
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'