Bonjour, Bonsoir
Aujourd'hui je vais vous présenter mon implémentation en C du chiffre de Vernam ou l'opération XOR qui découle de ce chiffrement, j'y ai vraiment mis du plaisir à le faire, pour une fois :-), c'est une implémentation relativement simple, relativement oui, j'en ai chier pour en venir à bout.
Donc pour présenter le chiffrement de Vernam c'est un algorithme de chiffrement tout bête qui est "incassable", "inviolable", que ce soit par bruteforce ou autre techniques version grand-maître du cryptanalyste.
On part du fait qu'il est impossible de trouver les additions qui ont formés une somme d'un entier:
? + ? = 100 | Où le premier point d'interrogation est le message original, et l'autre point d'interrogation, le masque jetable/clé, et 100 le message chiffré. Comment est-ce possible ? C'est effectivement impossible de retrouver le message original du fait que toute les possibilités sont possiblement possibles:
50+50 ; 51+49 ; 52+48 ; 53+47 ; etc...
Plutôt bête non ? :-)
Mais cependant on peut pas laisser un tel algorithme nous passer entre les doigts sans lui donner quelques (légers) désavantages.
-Le masque/clé doit faire la même taille que le message original (oui, le chiffre de vernam est une opération bit à bit).
-La clé doit être choisit aléatoirement.
-Le masque/clé ne doit servir uniquement qu'une fois
Et si on respecte scrupuleusement toutes ces conditions, on a le droit à une sécurité absolue, il parait.
J'vous fait un exemple en live avec de l'ascii (non-étendu, de 0 à 127):
On va prendre le chiffre à chiffrer M=1337 et la clé aléatoire (à 100%) C=FAAG , si on additionne ça (avec les correspondances décimales):
49|51|51|55
+
70|65|65|71
___________
119|116|116|126 , ce qui donne en ASCII: wtt~
Et s'il venait que votre addition dépasse la table ascii, auquel vous auriez une addition comme ceci:
49|51|51|105
+
70|65|65|71
___________
119|116|116|176
Ne vous inquiétez pas, nul besoin d'utiliser ascii étendu qui va jusqu'à 255, vous avez juste besoin de faire un modulo (ou une soustraction) du nombre maximum de caractères ascii ou de la norme sur laquelle vous travaillez, (si ça avait été du base64, un modulo 64 tout simplement) et en non étendu c'est 128, donc ça fait:
176%128 = 48
Maintenant place au code de mon implémentation, je doute qu'il soit digne d'un ingénieur informatique, donc n'hésitez pas à critiquer ou à me poser des questions si ça vous chagrine.
Aujourd'hui je vais vous présenter mon implémentation en C du chiffre de Vernam ou l'opération XOR qui découle de ce chiffrement, j'y ai vraiment mis du plaisir à le faire, pour une fois :-), c'est une implémentation relativement simple, relativement oui, j'en ai chier pour en venir à bout.
Donc pour présenter le chiffrement de Vernam c'est un algorithme de chiffrement tout bête qui est "incassable", "inviolable", que ce soit par bruteforce ou autre techniques version grand-maître du cryptanalyste.
On part du fait qu'il est impossible de trouver les additions qui ont formés une somme d'un entier:
? + ? = 100 | Où le premier point d'interrogation est le message original, et l'autre point d'interrogation, le masque jetable/clé, et 100 le message chiffré. Comment est-ce possible ? C'est effectivement impossible de retrouver le message original du fait que toute les possibilités sont possiblement possibles:
50+50 ; 51+49 ; 52+48 ; 53+47 ; etc...
Plutôt bête non ? :-)
Mais cependant on peut pas laisser un tel algorithme nous passer entre les doigts sans lui donner quelques (légers) désavantages.
-Le masque/clé doit faire la même taille que le message original (oui, le chiffre de vernam est une opération bit à bit).
-La clé doit être choisit aléatoirement.
-Le masque/clé ne doit servir uniquement qu'une fois
Et si on respecte scrupuleusement toutes ces conditions, on a le droit à une sécurité absolue, il parait.
J'vous fait un exemple en live avec de l'ascii (non-étendu, de 0 à 127):
On va prendre le chiffre à chiffrer M=1337 et la clé aléatoire (à 100%) C=FAAG , si on additionne ça (avec les correspondances décimales):
49|51|51|55
+
70|65|65|71
___________
119|116|116|126 , ce qui donne en ASCII: wtt~
Et s'il venait que votre addition dépasse la table ascii, auquel vous auriez une addition comme ceci:
49|51|51|105
+
70|65|65|71
___________
119|116|116|176
Ne vous inquiétez pas, nul besoin d'utiliser ascii étendu qui va jusqu'à 255, vous avez juste besoin de faire un modulo (ou une soustraction) du nombre maximum de caractères ascii ou de la norme sur laquelle vous travaillez, (si ça avait été du base64, un modulo 64 tout simplement) et en non étendu c'est 128, donc ça fait:
176%128 = 48
Maintenant place au code de mon implémentation, je doute qu'il soit digne d'un ingénieur informatique, donc n'hésitez pas à critiquer ou à me poser des questions si ça vous chagrine.
Code:
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> /**Implémentation personnelle du chiffre de vernam**/ int generate_mask(int len_c,unsigned char *mask) { srand (time(NULL)); int i; for(i=0;i<len_c;++i) mask[i]=rand()% 255 + 1; // clé aléatoire comprise entre 1 et 255, ascii étendu, d'où les unsigned char, les signed ne vont que jusqu'à +127 (ascii non étendu) // je pars de 1 et pas de 0, parce qu'en ASCII, le 0 vaut NULL et si jme tape ça dans ma string, le C va penser que mon string est trop court ( :-) ) mask[len_c]='\0'; return 0; } int generate_encryption(unsigned char *cipher,unsigned char *mask,unsigned char *crypted,int len_c) { int i; for(i=0;i<len_c;++i) { if( (mask[i]+cipher[i]) > 255 ) // Le résultat de l'addition est-il plus grand que la table ? crypted[i]=(mask[i]+cipher[i]) % 255; // si oui je fais un modulo else crypted[i]=mask[i]+cipher[i]; // sinon je mets ça dans crypted sans modulo } crypted[len_c]='\0'; return 0; } int main(int argc, char *argv[]) { if(argc == 2) { int len_c=strlen(argv[1]); unsigned char *mask=(unsigned char *)malloc(sizeof(char)*len_c+1); unsigned char *crypted=(unsigned char *)malloc(sizeof(char)*len_c+1); generate_mask(len_c,mask); generate_encryption((unsigned char *)argv[1],mask,crypted,len_c); printf("Message: %s\n Mask: %s\n Crypted: %s\n",argv[1],mask,crypted); free(mask); free(crypted); } else fprintf(stderr,"Usage: ./<executable> <text to encrypt>"); }
Commentaire