#include<stdio.h> #include<gmp.h> #define CLEAR_BUFFER while(getchar() != '\n') #define MSG_SIZE 500 #define KEY_SIZE 20 #define NB_LETTRES 26 /********************************************************/ /* Ce programme propose a son utilisateur de saisir un message et effectue ensuite son chiffrement par la methode Vigenere. Il est aussi possible de dechiffrer. Nous indicerons les lettres de 0 a 25. Le message "abz" sera donc represente par la suite de nombres 0 1 25. On chiffrera en decalant les lettres d'une position dans l'alphabet si la cle est un 'a', deux positions si c'est un 'b', etc. "abz" chiffre avec la cle "ab" nous donne donc "bda". Pour dechiffrer "bda", on inverse la cle "ab", ce qui nous donne "yx", et on applique la cle "yx" au message chiffre "bda". */ /********************************************************/ /* Saisit proprement une chaine de caractere. Supprime le caractere de retour a la ligne. */ void saisitChaine(char* message, int maxSize) { int i; fgets(message, maxSize, stdin); i = 0; while(message[i] != 0) i++; if (i > 0 && message[i-1] != '\n') CLEAR_BUFFER; else message[i-1] = 0; } /********************************************************/ /* Retourne vrai ssi a est une lettre minuscule ou majuscule de l'alphabet. */ int validChar(char a) { return (a >= 'A' && a <= 'z'); } /********************************************************/ /* Convertit a en minuscule s'il n'est pas deja sous ce format. */ char formatChar(char a) { if (a >= 'A' && a <= 'Z') return a - 'A' + 'a'; return a; } /********************************************************/ /* Supprime tous les caracteres non alphabetiques de message. place le resultat dans cleaned. Il doit etre possible d'utiliser la meme adresse pour cleaned et message. */ void cleanMessage(char* cleaned, char* message) { if (*message ==0 ) *cleaned = 0; else { if (validChar(*message)) { *cleaned = formatChar(*message); cleanMessage(cleaned + 1, message + 1); } else cleanMessage(cleaned, message + 1); } } /********************************************************/ /* Affiche la chaine message, puis un retour a la ligne. */ void printMessage(char* message) { printf("%s\n", message); } /********************************************************/ /* Retourne le rang de letter dans l'alphabet. On indice a partir de 0. */ char rankOfLetter(char letter) { return (letter - 'a'); } /********************************************************/ /* Retourne la lettre de rang rank. 'a' est de rang 0. */ char letterOfRank(char rank) { return (rank + 'a'); } /********************************************************/ /* Retourne le nombre de nombre de decalage dans l'alphabet a effectuer pour chiffrer avec la cle key. 1 pour 'a', 2 pour 'b', etc. Vous prendrez en compte le cas ou il y a 26 decalages a effectuer... */ char nbDecalagesOfKey(char key) { char nbDecalages = rankOfLetter(key) + 1; return (nbDecalages == NB_LETTRES) ? 0 : nbDecalages ; } /********************************************************/ /* Retourne la lettre de la cle correspondant a un decalage de rank lettres. */ char keyOfNbDecalages(char nbDecalages) { return (nbDecalages == 0) ? letterOfRank(NB_LETTRES) : letterOfRank(nbDecalages - 1); } /********************************************************/ /* Chiffre le caractere a avec la cle key, representee par une lettre de l'alphabet. */ char encryptChar(char a, char key) { return letterOfRank( (rankOfLetter(a) + nbDecalagesOfKey(key) )%(NB_LETTRES) ); } /********************************************************/ /* Inverse la cle de chiffrement key de sorte qu'on puisse l'utiliser pour le dechiffrement. Par exemple, l'inverse de 'a' est 'y', l'inverse de 'b' est 'x', l'inverse de 'c' est 'w', etc. */ char reverseKey(char key) { char nbDecalages = nbDecalagesOfKey(key); return (nbDecalages == NB_LETTRES) ? NB_LETTRES : keyOfNbDecalages(NB_LETTRES - nbDecalages); } /********************************************************/ /* Inverse toutes les lettres de keys. */ void reverseKeys(char* keys) { if (*keys != 0) { *keys = reverseKey(*keys); reverseKeys(keys + 1); } } /********************************************************/ /* Chiffre message avec key, place le resultat dans ciphered. message est suppose ne contenir que des caracteres alphabetiques au format minuscule. */ void encrypt(char* ciphered, char* message, char* key) { int i; for(i = 0 ; *message != 0 && *(key + i) != 0 ; i++, message++, ciphered++) { *ciphered = encryptChar(*message, *(key + i)); } if(*(key + i) == 0) encrypt(ciphered, message, key); else *ciphered = 0; } /********************************************************/ /* Dechiffre ciphered, place le resultat dans message. key est la cle qui a servi pour le chiffrement. */ void decrypt(char* message, char* ciphered, char* key) { reverseKeys(key); encrypt(message, ciphered, key); } /********************************************************/ /* Saisit un message, une cle, nettoie le message et affiche le message chiffre. */ void VigenereEncrypt() { char msg[MSG_SIZE]; char key[KEY_SIZE]; char chiffre[MSG_SIZE]; printf("Saisissez le message :\n"); saisitChaine(msg, MSG_SIZE); cleanMessage(msg, msg); printf("Saisissez la cle :\n"); saisitChaine(key, KEY_SIZE); encrypt(chiffre, msg, key); printf("Le message chiffre est :\n"); printMessage(chiffre); } /********************************************************/ /* Saisit un message chiffre, la cle de chiffrement, et affiche le message dechiffre. */ void VigenereDecrypt() { char msg[MSG_SIZE]; char key[KEY_SIZE]; char chiffre[MSG_SIZE]; printf("Saisissez le message chiffre :\n"); saisitChaine(chiffre, MSG_SIZE); printf("Saisissez la cle :\n"); saisitChaine(key, KEY_SIZE); decrypt(msg, chiffre, key); printf("Le message dechiffre est :\n"); printMessage(msg); } /********************************************************/ /* Donne a l'utilisateur la possibilite de chiffrer un message, dechiffrer un message, ou de quitter. */ void vigenere() { char choix[2]; do { printf("\n(c)hiffrer, (d)echiffrer, (q)uitter (c/d/q) ?"); saisitChaine(choix, 2); switch(*choix) { case 'c': VigenereEncrypt(); break; case 'd': VigenereDecrypt(); break; case 'q': printf("Au revoir !\n"); } } while(*choix != 'q'); } /********************************************************/ /* Pour tester les fonctions... */ int main() { vigenere(); return 0; }