venerdì 16 aprile 2010

Il cifrario di Vigenere

Il cifrario di Vigenere applica al testo da codificare la seguente sostituzione: i caratteri che compongono le parole vengono spostati di n posti in virtù di una parola (detta worm, verme) che stabilisce per ognuno di questi lo scostamento. A differenza del cifrario di Cesare che applica ai caratteri della parola sempre lo stesso scostamento (Cesare, ad esempio, spostava in avanti i caratteri di tre posizioni), il cifrario di Vigenere applica ai caratteri uno scostamento variabile! Ad ogni carattere della parola da codificare viene sommato il carattere del verme scelto (che può essere una semplice parola o anche un versetto). Un indice punta sempre al carattere del verme, quando l'indice (che viene incrementato ad ogni somma) giunge all'ultimo carattere del verme viene di nuovo fatto puntare al primo carattere! Tale rotazione deve poi avvenire anche sul carattere codificato. Pertanto, se la somma fra i caratteri (quello del verme e quello della parola in chiaro) sposta il carattere codificato oltre la lettera Z, gli scostamenti riprendono allora dalla lettera A. La decodifica avviene allora sottraendo lo scostamento indicato dal carattere del verme al carattere codificato. Nel programma che propongo l'input e l'output avvengono su file. In fase di codifica il programma chiede il nome di un file da codificare e ne verifica l'esistenza. Viene poi chiesta la parola da usare come verme. L'operazione di codifica produce il file file_codificato.txt. In fase di decodifica viene invece chiesto il file da decodificare, al termine dell'operazione è possibile trovare il file file_decodificato.txt contenente il testo di partenza!

/* cifrario di vigenere */
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define MAX_LENGTH 1024

int exist(char file_name[MAX_LENGTH]);
void code(char source_file_name[MAX_LENGTH],char worm[MAX_LENGTH]);
void decode(char source_file_name[MAX_LENGTH],char worm[MAX_LENGTH]);

int main(void) {
   int choice,worm_length;
   char worm[MAX_LENGTH];
   char file_name[MAX_LENGTH];
   FILE *source_file;

   do {
      printf("1. codifica;\n");
      printf("2. decodifica;\n");
      printf("Scelta: ");
      scanf("%d",&choice);
   } while (choice!=1 && choice!=2);
   if (choice==1) { /*code */
      getchar();
      printf(" Codifica file:\n");
      printf(" - Seme: ");
      fgets(worm,sizeof(worm),stdin);
      worm[strlen(worm)-1]=0;
      worm_length=strlen(worm);
      printf(" - Lunghezza del seme: %d\n",worm_length);
      printf(" - File sorgente: ");
      fgets(file_name,sizeof(file_name),stdin);
      file_name[strlen(file_name)-1]=0;
      if (exist(file_name)==0) {
         printf("Attenzione: il file %s non esiste!\n",file_name);
         return -1;
      }
      printf(" - Codifica: ");
      code(file_name,worm);
      printf(" completata!\n");
   }
   else if(choice==2) { /* decode */
      getchar();
      printf(" Decodifica file:\n");
      printf(" - Seme: ");
      fgets(worm,sizeof(worm),stdin);
      worm[strlen(worm)-1]=0;
      worm_length=strlen(worm);
      printf(" - Lunghezza del seme: %d\n",worm_length);
      printf(" - File sorgente: ");
      fgets(file_name,sizeof(file_name),stdin);
      file_name[strlen(file_name)-1]=0;
      if (exist(file_name)==0) {
         printf("Attenzione: il file %s non esiste!\n",file_name);
         return -1;
      }
      printf(" - Decodifica: ");
      decode(file_name,worm);
      printf(" completata!\n");
   }
   return 0;
}

/* verifica l'esistenza di un file, 1 altrimenti 0 */
int exist(char file_name[MAX_LENGTH]) {
   int result;
   FILE *source_file;
   if ((source_file=fopen(file_name,"r"))==NULL) result=0;
   else {
      result=1;
      fclose(source_file);
   }
   return result;
}

/* codifica un file */
void code(char source_file_name[MAX_LENGTH],char worm[MAX_LENGTH]) {
   int worm_length=strlen(worm),j,i=0;
   FILE *source_file=fopen(source_file_name,"r");
   FILE *output_file=fopen("file_codificato.txt","w");
   char c,next_worm_char,code_char;
   while ((c=fgetc(source_file))!=EOF) {
      if(isalpha(c)!=0) {
         code_char=c;
         next_worm_char=worm[i++]-'A';
         for (j=0;j<next_worm_char;j++) {
            if(code_char>='A' && code_char<='Z') {
               if(code_char=='Z') code_char='A';
               else code_char++;
            }
            else if(code_char>='a' && code_char<='z') {
               if(code_char=='z') code_char='a';
               else code_char++;
            }
         }
         if (i==worm_length) i=0;
         fputc(code_char,output_file);
      }
      else {
         fputc(c,output_file);
      }
   }
   fclose(source_file);
   fclose(output_file);
}

/* decodifica un file */
void decode(char source_file_name[MAX_LENGTH],char worm[MAX_LENGTH]) {
   int worm_length=strlen(worm),j,i=0;
   FILE *source_file=fopen(source_file_name,"r");
   FILE *output_file=fopen("file_decodificato.txt","w");
   char c,next_worm_char,decode_char;
   while ((c=fgetc(source_file))!=EOF) {
      if(isalpha(c)!=0) {
         decode_char=c;
         next_worm_char=worm[i++]-'A';
         for (j=next_worm_char;j>0;j--) {
            if(decode_char>='A' && decode_char<='Z') {
               if(decode_char=='A') decode_char='Z';
               else decode_char--;
            }
            else if(decode_char>='a' && decode_char<='z') {
               if(decode_char=='a') decode_char='z';
               else decode_char--;
            }
         }
         if (i==worm_length) i=0;
         fputc(decode_char,output_file);
      }
      else {
         fputc(c,output_file);
      }
   }
   fclose(source_file);
   fclose(output_file);
}

Nessun commento:

Posta un commento