Archi Projet Chiffrement

Identification

Infoforall

16 - Projet XOR


Evaluation ✎ : -

Documents de cours :

1 - Encoder un message sous forme d'une suite de bits

Nous allons revoir comment on parvient à encoder une suite de caractères quelconque en une suite d'octets et donc de bits.

Etape 1 : obtenir un tableau contenant les octets

Il faudra donc utiliser un encodage précis. Nous allons travailler avec l'UTF-8, le standard actuel.

Pour rappel, cet encodage utilise un nombre variable d'octets pour coder les caractères :

  • Les 128 caractères ASCII tiennent sur un octet uniquement.
  • Les caractères courants (surtout occidentaux) tiennent sur 2 octets
  • Certains caractères prennent 3 octets
  • D'autres caractères prennent 4 octets

01° Utiliser la fonction suivante pour visualiser la transformation de votre chaîne de caractères en suite de valeurs (entre 0 et 255 puisqu'il s'agit d'une suite d'octets).

1 2 3 4 5 6 7
def tab_octets(chaine:str) -> list[int]: """Renvoie un tableau contenant les octets encodant la chaîne en UTF-8""" octets = chaine.encode('utf-8') return list(octets) message = "AbCé" # Votre message t_o = tab_octets(message) # Un tableau d'octets représentant le message

On obtient ainsi :

>>> message 'AbCé' >>> t_o [65, 98, 67, 195, 169]

Combien d'octets pour le A, le b et le C ?

Combien d'octets pour le é ? Pourquoi ?

Etape 2 : Transformer le tableau d'octets stockés sous forme d'entier sous forme d'un tableau de bits ne comportant que des 0 et des 1.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
def tab_bits(t_octets:list[int]) -> list[int] : """Renvoie un tableau 8 fois plus long où chaque case est un bit plutôt qu'un octet""" reponse = [] for octet in t_octets: # pour chaque valeur décimale d'octets lue dans t_octets bits = f'{octet:08b}' # On transforme chaque valeur en string symbolisant les 8 bits for bit in bits: # pour chaque caractère bit dans le string bits reponse.append( int(bit) ) # Ajoute ce bit dans le tableau return reponse def tab_octets(chaine:str) -> list[int]: """Renvoie un tableau contenant les octets encodant la chaîne en UTF-8""" octets = chaine.encode('utf-8') return list(octets) message = "AbCé" # Votre message t_o = tab_octets(message) # Un tableau d'octets représentant le message t_b = tab_bits(t_o) # Un tableau de bits représentant le message

02° Vérifier que le tableau t_b des bits est bien 8 fois plus long que le tableau t_o des octets. Vérifier ensuite que les 8 premiers bits du tableau t_b représentent bien la valeur décimale 65, qui encode un A.

2 - Gestion de la clé du XOR

Nous allons vouloir utiliser le chiffrement symétrique basé sur XOR.

03° Modifier le programme qui stocke une clé et un message sous forme de string et qui permet d'obtenir le message et la clé représentés sous forme de deux tableaux de bits.

04° Compléter la table de vérité du XOR (OU eXclusif).

a b a XOR b
0 0 ?
0 1 ?
1 0 ?
1 1 ?

...CORRECTION...

a b a XOR b
0 0 0
0 1 1
1 0 1
1 1 0

05° Créer une fonction (à base d'instructions conditionnelles) xor qui renvoie la valeur a XOR b dont voici le prototype :

xor(a:'int 0 ou 1', b:'int 0 ou 1') -> 'int 0 ou 1'

Puisqu'en Python, 0 symbolise Faux et 1 Vrai, nous aurions pu (presque) noter ceci :

xor(a:bool, b:bool) -> bool

06° Créer une fonction (à base d'opérateurs logiques) xor qui renvoie la valeur a XOR b dont voici le prototype :

xor(a:'int 0 ou 1', b:'int 0 ou 1') -> 'int 0 ou 1'

07° Python possède bien un opérateur bit à bit XOR. Utiliser ce programme et vérifier bit par bit que l'opérateur Python ^ permet de réaliser un ET bit à bit entre les deux entrées fournies.

1 2 3 4 5 6 7
x = 0b1011 y = 0b110 z = x ^ y print(f"x {x:08b}") print(f"y {y:08b}") print(f" {'-' * 8}") print(f"x^y {z:08b}")

...CORRECTION...

x 00001011 y 00000110 -------- x^y 00001101

Si on regarde la colonne jaune, on obtient bien (0 XOR 1) = 1

Si on regarde la colonne bleue, on obtient bien (1 XOR 1) = 0

Si on regarde la colonne verte, on obtient bien (1 XOR 0) = 1

3 - Chiffrement XOR bit à bit

08° Créer une fonction chiffrement_bit_a_bit() qui attend le tableau de bits encodant le message, le tableau de bits encodant la clé et qui

    Créer une copie mc du tableau aussi grand que le message;

    Pour chaque indice i du tableau mc :

    • On remplit cette case d'indice i avec le XOR entre la case d'indice i dans le tableau du message et la case d'indice (i modulo longueur de la clé) dans le tableau de la clé.
    • On renvoie mc

    chiffrement_bit_a_bit(bits_message:list[int], bits_cle:list[int]) -> list[int]

09° Utiliser votre fonction pour obtenir le message chiffré. Utiliser ensuite à nouveau votre fonction sur le message crypté pour retrouver la suite de bits d'origine.

4 - Chiffrement XOR octet par octet

10° Puisque Python possède l'opérateur XOR bit à bit entre deux entiers, nous pouvons l'utiliser directement plutôt que de faire nous même la fonction chiffrement_bit_a_bit().

Réaliser donc la fonction chiffrement() qui reçoit les octets du message et les octets de la clé.

chiffrement(octets_message:list[int], octets_cle:list[int]) -> list[int]

La réponse est donc un tableau d'entiers compris entre 0 et 255.

5 - Avec un fichier ?

Pour l'instant, vous ne savez chiffrer que des textes. Or, on peut également chiffrer un fichier image, un fichier vidéo, ou n'importe quel autre type de fichier. Après tout, un fichier, c'est juste une suite d'octets.

11° Rechercher sur le Web comment ouvrir un fichier en mode binaire. On parle de fichier binaire.

12° Rechercher sur le Web comment créer un fichier en mode binaire et écrire des octets dans ce fichier.

13° Créer un fichier texte.

14° Créer un programme Python qui ouvre le un fichier en mode bianire et crée un nouveau fichier binaire contenant les octets du premier après chiffrement par une clé.

15° Utiliser votre programme sur un fichier image. En l'appliquant deux fois, vous devriez pouvoir obtenir au final une copie de votre fichier initial.

Il faudra sans doute encoder et décoder

6 -

7 -

8 -

Activité publiée le 04 10 2020
Dernière modification : 04 10 2020
Auteur : ows. h.