Le masque jetable, également appelé chiffre de Vernam, est un algorithme de cryptographie inventé par Gilbert Vernam en \(1917\) et perfectionné par Joseph Mauborgne, qui rajouta la notion de clé aléatoire.
Le chiffrement par la méthode du masque jetable consiste à combiner le message en clair avec une clé présentant les caractéristiques très particulières suivantes :
la clé doit être une suite de caractères au moins aussi longue que le message à chiffrer ;
les caractères composant la clé doivent être choisis de façon totalement aléatoire ;
chaque clé, ou « masque », ne doit être utilisée qu'une seule fois (d'où le nom de masque jetable).
Principe
Ce chiffre peut aisément se faire à la main, mais nous verrons ici la version informatisée qui repose sur l'opérateur OU-exclusif :
on dispose d’un message écrit avec des caractères alphabétiques ;
on remplace chaque caractère du message par un entier représentant sa valeur Unicode ;
on crée alors de manière aléatoire une clé de même longueur que le message et constituée d’entiers (au lieu de caractères dans la version initiale) ;
on effectue une opération OU-exclusif deux à deux entre les nombres du message et ceux de la clé : la liste ainsi obtenue est le message chiffré.
Pour déchiffrer le message on refait la même opération avec cette même clé.
Question 1 : génération de la clé
Compléter la fonction generation_cle qui crée une clé aléatoire (sous forme d'une liste d'entiers compris entre \(0\) et \(255\)) dont la taille est passée en paramètre.
Nous aurons besoin dans cet exercice de la fonction ou_exclusif qui prend en paramètres deux entiers compris entre \(0\) et \(255\) et renvoie un nombre entier résultat de l'opération.
L'opérateur logique ou exclusif suit la table de vérité suivante :
a
b
S
0
0
0
0
1
1
1
0
1
1
1
0
L'opération ou exclusif entre deux entiers est réalisée en faisant un ou exclusif bit à bit entre les représentations binaires de ces deux entiers.
Ainsi 1 XOR 3 revient à faire :
Compléter la fonction test_ou_exclusif qui permet de tester la fonction ou_exclusif et renvoie True si la fonction est correcte, et False sinon.
Le jeu de tests sera appliqué à cinq versions de la fonction ou_exclusif, une correcte et quatre incorrectes. (La version chargée en mémoire ne renvoie pas toujours la bonne réponse...)
Le jeu de tests devra donc être suffisant pour valider la version correcte et invalider les versions incorrectes.
###(Dés-)Active le code après la ligne # Tests (insensible à la casse) (Ctrl+I)
Entrer ou sortir du mode "deux colonnes" (Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran" (Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
Question 3 : transformation entre chaîne de caractères et liste d'entiers
Il est nécessaire de transformer la chaîne de caractères qui représente le message à envoyer en une liste de nombres entiers.
Pour ce faire, on remplace chaque caractère du message par la valeur Unicode associée, que l’on regroupe dans une même liste.
Compléter la fonction message_en_entiers qui prend en paramètre une chaîne de caractères et renvoie une liste d'entiers compris entre \(0\) et \(255\) représentant les valeurs Unicode de chaque caractère.
Compléter la fonction entiers_en_message qui prend en paramètre une liste d'entiers compris entre \(0\) et \(255\) et renvoie la chaîne de caractères correspondante.
codage d'un caractère
On rappelle qu'un caractère est encodé par un nombre entier que l'on obtient avec la fonction ord. Par exemple ord('A') est évalué à \(65\). Les codes des caractères alphabétiques non accentués en majuscule se suivent : ord('A') vaut \(65\), ord('B') vaut \(66\), ord('C') vaut \(67\), ...
Réciproquement, étant donné un entier positif, on obtient le caractère encodé par cet entier avec la fonction chr. Par exemple chr(65) est évalué à 'A'.
###(Dés-)Active le code après la ligne # Tests (insensible à la casse) (Ctrl+I)
Entrer ou sortir du mode "deux colonnes" (Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran" (Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
On souhaite convertir un message clair en un message chiffré.
Pour cela :
on génère au préalable une clé aléatoire de la même taille que le message.
on convertit le message (sous forme d'une chaîne de caractères) en une liste d'entiers,
on réalise le cryptage par une opération OU exclusif.
Fonctions fournies
Les fonctions des questions précédentes sont toutes fournies et chargée en mémoire :
la fonction generation_cle qui crée une clé aléatoire (sous forme d'une liste d'entiers compris entre \(0\) et \(255\)) dont la taille est passée en paramètre ;
la fonction ou_exclusif qui prend en paramètres deux entiers compris entre \(0\) et \(255\) et renvoie un nombre entier résultat de l'opération ;
la fonction message_en_entiers qui prend en paramètre une chaîne de caractères et renvoie une liste d'entiers compris entre \(0\) et \(255\) représentant les valeurs Unicode de chaque caractère ;
la fonction entiers_en_message qui prend en paramètre une liste d'entiers compris entre \(0\) et \(255\) et renvoie la chaîne de caractères correspondante.
Écrire la fonction chiffrement_Vernam qui prend en paramètre un message sous forme d'une chaîne de caractères et une clé déjà générée sous la forme d'une liste d'entiers et qui renvoie le message chiffré, sous la forme d'une chaîne de caractères.
Pour une clé générée aléatoirement, le message chiffré sera à chaque fois différent. Il n'est donc pas possible de tester directement sa valeur.
En revanche, ce procédé est un chiffrage symétrique, ce qui signifie que la même clé permet de déchiffrer le message.
Cette méthode va encore plus loin avec l'opérateur Ou exclusif : si cet opérateur permet de trouver la valeur chiffrée à partir de la valeur en clair et la clé, ce même opérateur permet de retrouver la valeur en clair à partir de la valeur chiffrée et la clé.
On peux donc utiliser la même fonction chiffrement_vernam pour chiffrer et déchiffrer.
Représentation des caractères
Certains caractères de la table Unicode correspondent à des caractères de contrôle et ne peuvent être représentés à l'écran.
À l'intérieur d'une chaîne de caractères, il seront remplacés par leur code hexadécimal. Ainsi, le caractère de code 31 sera remplacé par \x1f.
###(Dés-)Active le code après la ligne # Tests (insensible à la casse) (Ctrl+I)
Entrer ou sortir du mode "deux colonnes" (Alt+: ; Ctrl pour inverser les colonnes)
Entrer ou sortir du mode "plein écran" (Esc)
Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)
Si activé, le texte copié dans le terminal est joint sur une seule ligne avant d'être copié dans le presse-papier
# Tests(insensible à la casse)(Ctrl+I)
(Alt+: ; Ctrl pour inverser les colonnes)
(Esc)