/* sileCrittem v0.2                                      */
/* Semplice implementazione di un algoritmo              */
/* crittografico a trasposizione, quest'ultima           */
/* realizzata a salti tra la catena di caratteri,        */
/* con aggiunta la possibilita' di creazione             */
/* e utilizzo di una propria chiave privata.             */
/*                                                       */
/*                                                       */
/* realizzato da: ~>^Silentium^<~                        */
/*       in data:  21/02/2004                            */
/*    ultimo agg:  26/02/2004                            */
/*    dedicato a: [Cron] Anacron Group Italy             */
/*      mia casa: www.autistici.org/anacron-group-italy  */
/*                                                       */
/*                                                       */
/* copyleft: questo codice puo' essere liberamente       */
/*           inserito in qualsiasi luogo ed il suo       */
/*           contenuto puo' essere modificato, purche'   */
/*           ne sia sempre menzionato l'autore...        */
/*                                                       */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define DIMPASS 100       /* Massima dimensione della passphrase */
#define DIMKEY 100        /* Dimensione iniziale della chiave privata */

int controllo (int argc, char *argv[]);
int inserisci (int *passwd);
int opzione (void);
void critta (char *argv[], int nuMagico, int argc);
void decritta (char *argv[], int nuMagico, int argc);
void erroreR (char argv[]);
void erroreW (char argv[]);
void erroreKey (char argv[]);
void generaChiave (char *argv[]);

int lunghezza=0;

int main (int argc, char *argv[]){
int passwd[DIMPASS], scelta, nuMagico;

controllo(argc, argv); 
nuMagico=inserisci(passwd);
scelta=opzione();
if(scelta)
      decritta(argv, nuMagico, argc);
else
      critta(argv, nuMagico, argc);
return 0;
}



int controllo (int argc, char *argv[]){
if(argc==2)
   generaChiave(argv);
else if(argc!=3 && argc!=4){
                 printf("\n\n\t\t***********************************************\n"
                            "\t\t****           sileCrittem v0.2            ****\n"
                            "\t\t***         semplice implementazione        ***\n"
                            "\t\t**      di un algoritmo a trasposizione      **\n"
                            "\t\t**      e utilizzo di una chiave privata     **\n"
                            "\t\t**               realizzato da               **\n"
                            "\t\t**              ~>^Silentium^<~              **\n"
                            "\t\t**         .::Anacron Group Italy::.         **\n"
                            "\t\t**                                           **\n"
                            "\t\t***  www.autistici.org/anacron-group-italy  ***\n"
                            "\t\t****                                       ****\n"
                            "\t\t***********************************************\n"
                            "\t\t*****            .:da usare:.             *****\n"
                            "\t\t****    .creazione della chiave privata.   ****\n"
                            "\t\t***           sileCrittem  fileKEY          ***\n"
                            "\t\t**       .crittazione e/o decrittazione.     **\n"
                            "\t\t*     sileCrittem fileIN fileOUT [fileKEY]    *\n\n");
                   exit(1);
                 }
    return 0;
  }


/* Funzione che immagazzina la passphrase inserita, e restituisce  */
/* all'ambiente chiamante il numero di cifre che la compongono.    */

int inserisci (int *passwd){
int i, nuMagico=0;
printf("\nInserisci la passphrase: ");
for(i=0; (passwd[i]=getchar())!='\n'; i++, lunghezza++)
    nuMagico+=passwd[i];    
passwd[i]='\0';
return nuMagico;
} 


int opzione (void){
int scelta, flag;
     printf("\n\t\t***********************************************\n"
              "\t\t****           Critta: digita  0           ****\n"
              "\t\t****         Decritta: digita  1           ****\n"
              "\t\t****             Esci: digita -1           ****\n"
              "\t\t***********************************************\n");
       do{
       printf("\t\t:#> ");
       scanf("%d",&scelta); 
       switch(scelta){
                        case 0: return 0;
                                break;
                        case 1: return 1;
                                break;
                       case -1:  exit(1);
                                break;
                       default: printf("\n\t\tL'opzione inserita e' scorretta\n\n\a");
                                flag=2;
                      }
       }while(flag==2);
} 


/* Inizio della funziona dedita alla crittazione :-) */

void critta (char *argv[], int nuMagico, int argc){
FILE *in, *out, *key;
int i, tmp=0, tmp2;


/* Si inizia controllando se i files cui si è fatta richiesta di accesso */
/* permettano la lettura e/o la scrittura, in caso negativo si chiama    */
/* la funzione che visualizza un messaggio di errore e si esce.          */

if((in=fopen(argv[1],"r"))==NULL)
    erroreR(argv[1]);
else if((out=fopen(argv[2],"w"))==NULL)
         erroreW(argv[2]);


if(argc==4){
    if((key=fopen(argv[3],"r"))==NULL)
        erroreKey(argv[3]);
       
while((tmp2=getc(key))!=EOF)
       tmp+=tmp2;
}


/* Inizio dell'algoritmo a trasposizione; vengono letti tutti i caratteri     */
/* presenti nel file in chiaro..nell'ordine d'indicizzazione:                 */
/* i pari vengono incrementati del numero ottenuto sommando tutti i caratteri */
/* della passphrase inserita in precedenza, mentre i dispari vengono          */
/* incrementati del numero formato dalle cifre che compongono quest'ultima.   */
/* Se si utilizza la chiave privata, essa viene letta e sommata con il numero */
/* rappresentante la lunghezza della passphrase precedentemente inserita      */
/* (indice dispari), per quanto riguarda invece l'indice pari, quest'ultima   */
/* viene sommata con le cifre che compongono la passphrase.                   */

if(argc==4)
   for(i=0; (tmp2=getc(in))!=EOF; i++){
   switch(i){
               case 1: tmp2+=tmp+lunghezza;
                       break;
               case 3: tmp2+=tmp+lunghezza;
                       break;
               case 5: tmp2+=tmp+lunghezza;
                       break;
               case 7: tmp2+=tmp+lunghezza;
                       break;
               case 9: tmp2+=tmp+lunghezza;
                         i=0;
                       break;
              default:  tmp2+=tmp+nuMagico;
                       break;
              }
     fprintf(out,"%c",tmp2);
   }

else 
    for(i=0; (tmp=getc(in))!=EOF; i++){
    switch(i){
               case 1: tmp+=lunghezza;
                       break;
               case 3: tmp+=lunghezza;
                       break;
               case 5: tmp+=lunghezza;
                       break;
               case 7: tmp+=lunghezza;
                       break;
               case 9: tmp+=lunghezza;  
                         i=0;
                       break;
              default:  tmp+=nuMagico;
                       break;
              }
    fprintf(out,"%c",tmp);
  }

fclose(in);
fclose(out);
}


/* Discorso contrario, ovvero l'algoritmo di cui sopra, viene eseguito    */
/* in maniera inversa..sottraendo quindi ad uno ad uno i caratteri        */
/* prelevati dal file crittato, con il numero generato dalla somma delle  */
/* cifre contenente la passphrase (indice pari); mentre i caratteri       */
/* relativi all'indice dispari, sottratti con il numero delle cifre che   */
/* compongono la passphrase precedentemente inserita.                     */
/* Se si adopera la chiave privata quest'ultima viene sommata con il      */
/* numero della lunghezza della passphrase precedentemente inserita       */
/* (indice dispari), per poi sottrarre il tutto con ogni carattere        */
/* prelevato dal file input.                                              */
/* Per quanto concerne invece l'indice pari, qui la chiave privata        */
/* viene sommata con il numero generato dalla somma delle cifre che       */
/* compongono la passphrase, il tutto poi sottratto con ogni carattere    */
/* prelevato dal file crittato.                                           */

void decritta (char *argv[], int nuMagico, int argc){
FILE *in, *out, *key;
int i, tmp=0, tmp2;

if((in=fopen(argv[1],"r"))==NULL)
    erroreR(argv[1]);
else if((out=fopen(argv[2],"w"))==NULL)
         erroreW(argv[2]);

if(argc==4){
    if((key=fopen(argv[3],"r"))==NULL)
        erroreKey(argv[3]);

while((tmp2=getc(key))!=EOF)
       tmp+=tmp2;
     }


if(argc==4)
     for(i=0; (tmp2=getc(in))!=EOF; i++){
     switch(i){
               case 1: tmp2-=tmp+lunghezza;
                       break;
               case 3: tmp2-=tmp+lunghezza;
                       break;
               case 5: tmp2-=tmp+lunghezza;
                       break;
               case 7: tmp2-=tmp+lunghezza;
                       break;
               case 9: tmp2-=tmp+lunghezza;
                         i=0;
                       break;
              default:  tmp2-=tmp+nuMagico;
                       break;
             }
    fprintf(out,"%c",tmp2);
  }

else
    for(i=0; (tmp=getc(in))!=EOF; i++){
    switch(i){
               case 1: tmp-=lunghezza;
                       break;
               case 3: tmp-=lunghezza;
                       break;
               case 5: tmp-=lunghezza;
                       break;
               case 7: tmp-=lunghezza;
                       break;
               case 9: tmp-=lunghezza;
                         i=0;
                       break;
              default:  tmp-=nuMagico;
                       break;
              }
    fprintf(out,"%c",tmp);
  }

fclose(in);
fclose(out);
}


/* Messaggio di errore chiamato per l'impossibilità di leggere e/o */
/* scrivere un file richiamato da linea di comando.                */ 

void erroreW (char argv[]){
    printf("\n\t\t   %p Errore nella creazione del file\n\n\a",argv);
    exit(1);
}

void erroreR (char argv[]){
    printf("\n\t\t   %p Errore nella lettura del file\n\n\a",argv);
    exit(1);
}

void erroreKey (char argv[]){
    printf("\n\t     %p Errore nella lettura della chiave privata\n\n\a",argv);
    exit(1);
}


/* Funzione che si occupa della generazione della chiave privata */

void generaChiave (char *argv[]){
FILE *chiave;
int i, scelta, key[DIMKEY], random[DIMKEY];

  printf("\n\t\t***********************************************\n"
           "\t\t**** Intendi procedere con la generazione  ****\n"
           "\t\t**** della tua chiave privata?             ****\n"
           "\t\t****                                       ****\n"
           "\t\t**** SI: digita 0                          ****\n"
           "\t\t**** NO: digita 1                          ****\n"
           "\t\t***********************************************\n"
           "\t\t:#> ");
  
scanf("%d",&scelta);
if(scelta)
     exit(1);
else
     if((chiave=fopen(argv[1],"w"))==NULL)
        erroreW(argv[1]);

     printf("\n\t\t     ..inizio della fase di generazione..\n"
            "\t\t         della propria chiave privata\n"
            "\t\t            tempo stimato: 2 minuti\n");


/* Utilizzo del generatore pseudo-casuale di interi a 48 bit, il    */
/* cui valore viene inizializzato ogni secondo mediante la funzione */
/* sleep(), tenendo conto dei secondi trascorsi a partire dal       */ 
/* 1 gennaio 1970.                                                  */

     for(i=0; i<DIMKEY-1; i++){
     srand48(time(NULL));
     key[i]=lrand48();
     sleep(1);
   }

printf("\n\t\tInserisci 100 caratteri in maniera casuale per\n"
         "\t\taumentare l'entropia nella generazione della\n"
         "\t\ttua chiave privata::\n\n");


/* Richiesta di inserimento di 100 caratteri in maniera randomica.     */
/* Il valore di quest'ultimi viene sommato agli interi precedentemente */
/* calcolati, ed il tutto viene scritto nel file puntato.              */

for(i=0; i<DIMKEY-1; i++){
   random[i]=getchar();
   key[i]+=random[i];
fprintf(chiave,"%d",key[i]);
}

printf("\n\t\t     Chiave privata creata con successo!!!\n\n");
exit(0);
}
