suivant: Changement de base
monter: Corrigés des programmes
précédent: Le plus beau métier
Table des matières
vigenere.c
#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;
}
suivant: Changement de base
monter: Corrigés des programmes
précédent: Le plus beau métier
Table des matières
klaus
2010-08-05