Convertir de grands nombres entiers en octets et inversement en Python

Vous avez une chaîne d’octets et vous devez la convertir en une valeur entière. Alternativement, vous devez convertir un grand nombre entier en une chaîne d’octets.

Supposons que votre programme a besoin de travailler avec une chaîne de 16 octets qui contient une valeur entière de 128 bits. Par exemple:

donnee = b'\x00\x124V\x00x\x90\xab\x00\xcd\xef\x01\x00#\x004'

Pour interpréter les octets comme un entier, utilisez int.from_bytes(), et spécifiez l’ordre des octets comme ceci:

>>> len(donnee)
16
>>> int.from_bytes(donnee, 'little')
69120565665751139577663547927094891008
>>> int.from_bytes(donnee, 'big')
94522842520747284487117727783387188
>>>

Pour convertir une grande valeur entière en une chaîne d’octets, utilisez la méthode int.to_bytes(), en spécifiant le nombre d’octets et l’ordre des octets. Par exemple:

>>> x = 94522842520747284487117727783387188
>>> x.to_bytes(16, 'big')
b'\x00\x124V\x00x\x90\xab\x00\xcd\xef\x01\x00#\x004'
>>> x.to_bytes(16, 'little')
b'4\x00#\x00\x01\xef\xcd\x00\xab\x90x\x00V4\x12\x00'
>>>

Convertir de grandes valeurs entières en/à partir de chaînes d’octets n’est pas une opération courante. Cependant, elle apparaît parfois dans certains domaines d’application, tels que la cryptographie ou les réseaux informatiques.

Par exemple, les adresses réseau IPv6 sont représentées par des nombres entiers sur 128 bits. Si vous écrivez du code qui doit extraire de telles valeurs d’un enregistrement de données, vous pourriez rencontrer ce problème.

Comme alternative à ce code, vous pouvez être tenté d’extraire les valeurs à l’aide du module struct, comme décrit dans l’article “Lecture et écriture de tableaux binaires de structures”.

Cela fonctionne, mais la taille des entiers qui peuvent être extraits avec struct est limitée. Ainsi, vous devrez déballer plusieurs valeurs et les combiner pour créer la valeur finale. Par exemple:

>>> donnee
b'\x00\x124V\x00x\x90\xab\x00\xcd\xef\x01\x00#\x004'
>>> import struct
>>> ho, ba = struct.unpack('>QQ', donnee)
>>> (ho << 64) + ba
94522842520747284487117727783387188
>>>

La spécification de l’ordre des octets (petit ou grand) indique tout simplement si les octets qui composent la valeur entière sont listés du plus petit au plus significatif ou inversement. C’est facile à voir en utilisant une valeur hexadécimale soigneusement conçue:

>>> x = 0x01020304
>>> x.to_bytes(4, 'big')
b'\x01\x02\x03\x04'
>>> x.to_bytes(4, 'little')
b'\x04\x03\x02\x01'
>>>

Si vous essayez d’insérer un entier dans une chaîne d’octets, mais qu’il ne convient pas, vous obtiendrez un message d’erreur. Vous pouvez utiliser la méthode int.bit_length() pour déterminer combien de bits sont nécessaires pour stocker une valeur si nécessaire:

>>> x = 523 ** 23
>>> x
335381300113661875107536852714019056160355655333978849017944067
>>> x.to_bytes(16, 'little')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: int too big to convert
>>> x.bit_length()
208
>>> nbytes, rem = divmod(x.bit_length(), 8)
>>> if rem:
...     nbytes += 1
...
>>>
>>> x.to_bytes(nbytes, 'little')
b'\x03X\xf1\x82iT\x96\xac\xc7c\x16\xf3\xb9\xcf...\xd0'
>>>

LAISSER UN COMMENTAIRE

Please enter your comment!
Please enter your name here