Tout a commencé un beau matin, il y a deux jours, lorsque je lisais un disque de cryptage pour enfants sur une petite boîte de carton. J'y ai vu un premier cercle dans lequel était inscrit notre alphabet habituel, composé de 26 caractères, et, dans un cercle plus petit à l'intérieur du premier cercle, un autre alphabet das lequel les lettres étaient placées aléatoirement. C'était l'illumination, bien qu'habituellement je ne sois pas un spécialiste de cryptologie.
Bref, je me suis lancé dans un projet : faire un code qui génèrerait une clé et à partir d'un alphabet choisi, crypter un message. En fait, la clé en question est un nouvel alphabet dans lequel les lettres sont placées aléatoirement.
Pour ceux qui liraient en diagonale, voici un récapitulatif des buts du programme (le 14/01/2006):
VERSION = 0.06 # le 14/01/2006 import sys, random, string, os types = ['--long-numeric','--numeric','--long-alpha','--alpha','--all-alpha',
\'--g-key-short','--g-key-long','--g-key-all','--g-alpha','--file'] a_low = string.lowercase a_ltr = string.letters d_all = string.digits a_all = (string.printable)[:95] # on ne sélectionne que les 95premiers caractères pour
ne pas avoir '\t\n\r\x0b\x0c'
a_low = 'abcdefghijklmnopqrstuvwxyz' a_ltr = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' d_all = '0123456789' a_all = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*\
+,-./:;<=>?@[\\]^_`{|}~ '
Je ne pense pas que je vais beaucoup m'attarder sur cette défintion qui est assez explicite de nom puisqu'elle affiche simplement l'aide en tuant le programme. Je l'affiche s'il y a une erreur.
raise SystemExit(die)Cette ligne est une manière pratique de tuer un programme Python. Il existe bien d'autres raise qui sont utilisables pour différentes raisons (par exemple SystemError retournera la ligne, la classe et la défintion dans laquelle le raise a été appelé).
Cette définition n'est appelée que si un fichier comportant une clé, un alphabet et un message n'a pas le bon format. En effet, pour simplifier la tâche, voici comment le fichier devrait être :
---ALPHABET---
abcdefghijklmnopqrstuvwxyz
---KEY---
uigkjtpmfbcryhwxvsqlazndoe
---MESSAGE---
thisisasimplemessage
Cette défintion, très simple, permet simplement d'afficher des listes lisiblement. La variable ltp est la variable contenant la liste et la variable sp qui est un nombre entier (int[eger]) ne sert qu'à savoir s'il faut ajouter ou non un espace entre chaque élément de la liste.
Ca se complique enfin !
neykey sert dans deux cas : lorsqu'on appelle le générateur de clés (en utilisant l'option --g-key-*) ou lorsqu'on veut crypter un message. La variable ct contient l'option passée au script (nous verrons les options à la fin de l'article). Comme vous avez pu le voir dans la liste types, il y a des sortes de sous-options : "long" et "all". Cela permet simplement de choisir l'alphabet. En effet, si 'long' est choisi, alors la clé est de 52 caractères (voir la variable a_ltr); si 'all' est choisi, alors la clé comporte 95 caractères (si rien d'autre n'est choisi, option '--numeric' par exemple).
global num_key; num_key = list() #creates an empty listOn met global devant num_key pour que la clé numérique soit considérée comme globale à tout le script. Cela signife que l'on n'aura pas besoin de la passer en tant qu'argument dans la définition de cryptage.
while x < kl: rand = int(random.uniform(0,kl)) if rand not in num_key: num_key.append(rand); x=x+1C'est là où les nombres aléatoires jouent leur rôle : on génère des nombres aléatoires puis on vérifie si le nombre généré est dans la liste. Si le nombre ne l'est pas, alors on l'ajoute à la liste. On fait ensuite de même avec la clé alphabétique si 'alpha' est dans l'option.
On commence encore une fois par vérifier quel alphabet utiliser, toujours en vérifiant si "long" est dans l'option.
if 'alpha' in ct_: # si un cryptage alphabétique est demandé alors ... alpha_c = list(); # on créé une liste for x in range(len(mss)): alpha_new = alpha_key[ltr.index(mss[x])] # voir plus bas alpha_c.append(alpha_new) # on ajoute à la liste plist(alpha_c,0)Explication de la ligne compliquée du code ci-dessus. Tout d'abord, d'après la définition newkey, alpha_key est la clé alphabétique. On va donc chercher dans le bon alphabet ltr la position de chacune des lettres du message mss (voir les lignes du code précédant le listing pour comprendre d'où vient ltr).
num_c = list(); for jt in range(len(mss)): num_new = num_key.index(ltr.index(mss[jt])) num_c.append(num_new) plist(num_c,0)On va crypter le message numériquement, ce qui signifie que le message sera toujours crypté deux fois : une fois numériquement (cela retournera une chaîne de chiffres) et une fois aplhabétiquement si spécifié. Je pense que vous avez trouvé la ligne compliquée que je vais expliquer. num_key.index() permet d'avoir la place du caractère demandé dans la clé numérique. Ainsi, on prend une première fois la position du caractère du message dans l'alphabet, puis la position de ce même caractère dans la clé. On ajoute enfin le tout à la liste qui sera, via la définition plist, la chaîne cryptée.
fcrypt à la même fonction que crypt à la différence près que le fcrypt va tout piocher (message, clé, alphabet) dans le fichier spécifié. Vous aurez remarqué que je ne vérifie pas l'existence du fichier dans cette définition puisque je le fait dans le code hors-définition que nous verrons plus tard.
if lines[0] != '---ALPHABET---\n' or lines[3] != '---KEY---\n' or \
lines[6] != '---MESSAGE---\n': print "Error: wrong file format"; f_help() alpha = lines[1]; key = lines[4]; mess = lines[7] # attribution aux variables
for x in range(len(mess)):
if mess[x] not in alpha or mess[x] not in key: print "Error:\tplease be sure \
that every character in your message is in the alphabet and in the key";help()
else: new = key[alpha.index(mess[x])]; cyph_m.append(new)
f.seek(0,2)
print >> f, '\n---CRYPTED MESSAGE---\n'+ciphered
f.close()
On commence par vérifier la présence d'arguments : s'il n'y en a aucun, on arrête le script en affichant l'aide. Puis, dans le else, on commence par définir la variable ct comme l'option (argument n°1). Ensuite viennent les étapes de vérification de l'option : si c'est une option de génération de clé ou d'alphabet, on affiche ce qu'il faut =). Si l'utilisateur demande une clé, alors on ajoute discrètement "alpha" à la variable 'ct' pour ne pas avoir à refaire une définition identique à new_key. Ensuite, si un fichier est proposé en tant que second argument, alors on vérifie l'existence du fichier, puis on affiche un message prévenant que des erreurs peuvent se produire dans le cadre de l'utilisation d'une clé personalisée.
Enfin, si ce n'est rien de tout ça, on fait le script normalement.
N'oubliez pas d'aller voir la page de projets pour plus d'infos sur l'avancée du code.