next up previous contents
suivant: Arithmétique monter: Vigenere précédent: Vigenere   Table des matières

Exercice 4 - Conversion en base 10

Adapter le programme de chiffrement par la méthode Vigenère de sorte qu'il possible de saisir les messages et les clés en base 10 plutôt qu'en base 26. Le message chiffré devra être affiché aussi en base 10. Il suffit pour ce faire de complèter les fonctions void toBase10(mpz_t result, char* message) et void fromBase10(char* message, mpz_t value).

vigenereGmpVide.c


#include<stdio.h>
#include<gmp.h>

#define CLEAR_BUFFER while(getchar() != '\n')
#define MSG_SIZE 500
#define KEY_SIZE 20
#define BASE 27
#define NB_LETTRES (BASE - 1)

/********************************************************/

/*
  Nous numeroterons les lettres de 1 a 27. Cela permettra 
  d'eviter qu'il y  ait des zeros dans la representation 
  en base 27.

  Nous transformerons ces messages en nombres 
  en les convertissant de la base 27 vers la base 10, 
  
  Par exemple,

  a b z = a + 27 (b + 27 (z)) = 1 + 27 * (2 + 27 * (26)).

  Il devra aussi etre possible de saisir les messages 
  et les cles directement en base 10.
*/

/********************************************************/

/*
  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);
}


/********************************************************/

/*
  Exprime message en base 10. Par exemple, si message = "abzc", 
  result = 1 + BASE (2 + BASE(26 + BASE(3)))
*/

void toBase10(mpz_t result, char* message) 
{
}

/********************************************************/

/*
  Effectue la transformation inverse de toBase10.
*/

void fromBase10(char* message, mpz_t value) 
{
}


/********************************************************/

/*
  Saisit soit une chaine, soit un nombre en base 10 
  converti par la suite en chaine.
*/

void saisitValeurs(char* valeurs, int maxSize) 
{
  mpz_t base10;  
  char choix[2];
  mpz_init(base10);
  do
    {
      printf("(c)haine, (b)ase 10 (c/b) ?"); 
      saisitChaine(choix, 2);
      switch(*choix)
	{
	case 'c': 
	  saisitChaine(valeurs, maxSize);
	  toBase10(base10, valeurs);	  
	  printf("(");
	  toBase10(base10, valeurs);
	  mpz_out_str(NULL, 10, base10);
	  printf(" en base 10)\n");	  
	  break;
	case 'b': 
	  saisitChaine(valeurs, maxSize);
	  mpz_set_str(base10, valeurs, 10);
	  fromBase10(valeurs, base10);	  
	  break;
	}
    }
  while(*choix != 'c' && *choix!='b');
  mpz_clear(base10);
}


/********************************************************/

/*
  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];
  mpz_t base10;
  printf("Saisissez le message :\n");
  saisitValeurs(msg, MSG_SIZE);
  cleanMessage(msg, msg);
  printf("Saisissez la cle :\n");
  saisitValeurs(key, KEY_SIZE);
  encrypt(chiffre, msg, key);
  printf("Le message chiffre est :\n");
  printMessage(chiffre);
  printf("(");
  mpz_init(base10);
  toBase10(base10, chiffre);
  mpz_out_str(NULL, 10, base10);
  printf(" en base 10)\n");
  mpz_clear(base10);
}

/********************************************************/

/*
  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];
  mpz_t base10;
  printf("Saisissez le message chiffre :\n");
  saisitValeurs(chiffre, MSG_SIZE);
  printf("Saisissez la cle :\n");
  saisitValeurs(key, KEY_SIZE);
  decrypt(msg, chiffre, key);
  printf("Le message dechiffre est :\n");
  printMessage(msg);
  printf("(");
  mpz_init(base10);
  toBase10(base10, msg);
  mpz_out_str(NULL, 10, base10);
  printf(" en base 10)\n");
  mpz_clear(base10);
}

/********************************************************/

/*
  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;
}



klaus 2010-08-05