Conversions entre format de données en python(byte, string, int)
- Conversion int <->Bytes
- int <-> string
- int <-> hex
- hexa string <-> bytes
- byte hexa string <-> bytes
- Sources
Cet article décrit différentes façons de convertir des données représentées dans des formats différents en python : byte à entier, string à byte, hexa string à byte, etc.
Lors des CTF(Capture the flags), il m’arrivait souvent de perdre du temps dans les conversion et de me mélanger les pinceaux, d’où cet article pour faciliter la compréhension.
[TOC]
Conversion int <->Bytes
Nativement
int -> bytes
Python3 possède la fonction int.to_bytes(length, byteorder, **, *signed=False) qui permet de convertir un entier en bytes. Elle est intéressante si on souhaite s’assurer de la taille en byte de la chaîne résultante.
length: Longueur de la chaîne de byte résultantebyteorder: Il faut pour cela spécifier si l’ordre est big ou little endian.
Exemple
Le code suivant :
integer = 2000
print("big : ", (integer).to_bytes(2, byteorder='big'))
print("little : ", (integer).to_bytes(2, byteorder='little'))
produira la sortie suivante :
big : b’\x07\xd0’
little : b’\xd0\x07’
Sources :
bytes -> int
int.from_bytes(bytes, byteorder, **, *signed=False)
Dans le sens inverse, on peut aussi convertir des bytes en int.
byteString = b"test"
print("big :", int.from_bytes(b'\x00\x10', byteorder='big'))
print("little :", int.from_bytes(b'\x00\x10', byteorder='little'))
print("big : ", int.from_bytes(byteString, byteorder='big'))
produira la sortie suivante :
big : 16
little : 4096
big : 1952805748
Avec la librairie Crypto
La librairie Crypto.Util.number permet d’effectuer des conversions (long en bytes et inversement) sans devoir indiquer le nombre de bytes résultant.
- Installation : pycryptodome
- Importation de la librairie
from Crypto.Util.number import long_to_bytes, bytes_to_long
- Exemple
byteString = b"test" integer = 2000 print("Byte -> int : ", byteString, "->", bytes_to_long(byteString)) print("int -> Byte : ", integer, "->",long_to_bytes(integer))
produira la sortie suivante :
Byte -> int : b’test’ -> 1952805748
int -> Byte : 2000 -> b’\x07\xd0’
Misc
Appliqués la fonctions bytes sur un entier va simplement construire un byte avec le nombre d’octets spécifiés par le nombre. Elle ne va pas convertir le nombre en bytes.
a = 0x10
b = bytes(a)
print("a = ", a, "b = ", b)
produira la sortie suivante :
a = 16 b = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
int <-> string
Pour ce faire, python3 implémente déjà nativement des fonctions :
- string -> int : str(…)
- int -> string : int(…)
integer = 2000
str_integer = "2000"
print("int -> string", integer, "->",str(integer))
print("string -> int : ", int(str_integer))
produira la sortie suivante :
int -> string 2000 -> 2000 string -> int : 2000
Avertissement :
Il faut que la string représente un nombre entier. Par exemple, le code suivant :
Astring = "A_String"
print(int(Astring ))
produira l’erreur suivante :
ValueError: invalid literal for int() with base 10: ‘A_String’
int <-> hex
Pour convertir des nombres hexadécimaux sous forme de string en int et inversement, il existe les fonctions suivantes :
- int(…)
- Il est nécessaire de préciser la base utilisée pour la conversion, avec des hexa, il s’agit ici de la base 16
Ressources complémentaires : stackoverflow.com - Convert hex string to int in Python
- hex(…)
Le code suivant :
integer = 2000
str_hex = "0x20"
print("string hexa -> int : ", str_hex, "->" , int(str_hex, 16))
print("int -> string hexa : ", integer, "->" , hex(integer))
produira la sortie suivante :
string hexa -> int : 0x20 -> 32
int -> string hexa : 2000 -> 0x7d0
hexa string <-> bytes
hexa string -> bytes
bytes.fromhex(string)
Il s’agit d’une fonction native fournie par python permettant de convertir un nombre hexa sous forme de string en byte.
Par exemple, le code suivant :
str_hex = "0x20"
StringHexa = "0x42"
StringHexa2 = "42"
print("hex string -> bytes : ", str_hex[2:], "->", bytes.fromhex(str_hex[2:]))
print("hex string -> bytes : ", str_hex[2:], "->", bytes.fromhex(str_hex[2:]))
print("hex string -> bytes : ", StringHexa[2:], "->",bytes.fromhex(StringHexa[2:]))
print("hex string -> bytes : ", StringHexa[2:], "->", bytes.fromhex(StringHexa2))
Produit la sortie suivante :
hex string -> bytes : 20 -> b’ ‘
hex string -> bytes : 20 -> b’ ‘
hex string -> bytes : 42 -> b’B’
hex string -> bytes : 42 -> b’B’
On peut constater que la transformation de 0x20 en byte ne donne rien car cette valeur n’a aucun sens en ascii.
Au contraire de 0x42 qui donne B
Avertissement :
Le nombre hexa, qui est sous format string, ne doit pas contenir le “0x” sinon cela provoquera l’erreur suivante :
ValueError: non-hexadecimal number found in fromhex() arg at position 1
Dans le code d’exemple ci-dessus, j’ai ajouté [2:] pour ne pas prendre le “0x”
Ressources complémentaires :
-
Documentation python : docs.python.org/fr/3.7/library/stdtypes.html
- Convertir hexadécimal en octet en Python
- 200ok.ch - hexlify() and unhexlify()
byte hexa string <-> bytes
binascii
La librairie binascii, comme son nom l’indique permet des conversions ascii <-> bytes avec les fonctions unhexlify et hexlify. Par exemple, le code suivant :
print("Hexa number -> byte string :", binascii.unhexlify(byteStringHexa))
print("byte string -> hexa number :", binascii.hexlify(byteString))
produira la sortie suivante :
hex string -> byte : b’42’ -> b’B’
byte string -> hexa number : b’test’ -> b’74657374’
Sources : docs.python.org/3/library/binascii.html