Privacy Policy Cookie Policy
You are here
Home > Programmazione > C/C++ > Cifratura Xor in C – Parte 2

Cifratura Xor in C – Parte 2

In questo secondo appuntamento implementeremo effettivamente la nostra funzione Xor ma prima di parlare di questo dobbiamo aggiungere un’altra funzione importante al progetto.
Un problema che si puà riscontrare in questi casi è che il numero di caratteri del testo non sia un multiplo del numero di caratteri della password.

Descrizione del problema

Questo può e non può essere un problema in base a come implementi la funzione Xor.
Se ad esempio per cifrare vuoi utilizzare tutti i caratteri della password, uno a uno, tante volte quanto basta per cifrare il testo, il numero di caratteri del testo deve essere un multiplo della password, se invece scorri la password tante volte fino a che non finisce il testo questo problema non si presenta.
La seconda implementazione, che è un miglioramento della prima la vedremo successivamente e può essere fatta tramite l’operazione modulo.

Implementiamo!

Vediamo subito come fare diventare il numero di caratteri del testo da cifrare un multiplo del numero di caratteri della password (Rendere il testo un multiplo della chiave di codifica è un processo utilizzato spesso in algoritmi di crittografia più complessi e professionali quindi lo re-incontreremo successivamente e cercheremo anche tecniche più efficienti per implementare una soluzione).

Prima implementazione

Il meccanismo di cifratura da me utilizzato in questo articolo è semplice e consiste nell’utilizzare ogni lettera della password per cifrare ogni carattere del testo.
Finiti i caratteri della password si riparte dal primo.
Questo meccanismo sfrutta la dimensione in caratteri della password per settare il contatore.

Questo algoritmo ha però una falla, se non la trovate ve la dico a fine articolo 😉

Se le cifre che compongono il testo non sono un multiplo delle cifre che compongono la password, il conteggio sballa, capirete successivamente perchè.
Per conodità ho quindi implementato la funzione che aggiunge un determinato numero di zeri, dipendente dalla dimensione della password. Con tutta la fantasia di questo mondo ho dato a tale funzione il nome di Aggiungi_Zeri().
La funzione controlla che il numero di caratteri del testo sia un multiplo del numero di caratteri della password, in caso contrario, aggiunge tanti zeri alla fine dello stesso quanto basta a renderlo tale.

char *Aggiungi_Zeri(char *testo,int dimensione){

int i=0,j=0,lunghezzastringa=0,contatore=0,zeri=0;

/* conterra il testo con gli zeri, è stata dichiarata come globale ma questa è una pratica sconsigiata, vedremo come potere migliorarlo */
testozeri = NULL;

// Se il testo è lungo?? quanto costerà queta funzione?? (si potrebbero aprire capitoli, queste cose le vedremo nella sezione specifica)
lunghezzastringa=(ContaCaratteri(testo)); /* Conta caratteri è una funzione che conta i caratteri della stringa (strlen()) */

//Lunghezza stringa conterrà ora il numero di caratteri della password.

contatore=lunghezzastringa;

// Devo trovare il primo multiplo... secondo voi è il metodo migliore?? per niente... (vi posterò il link appena sarà pronto l'articolo)
while((contatore%dimensione)!=0)
contatore++;

zeri=contatore-lunghezzastringa;

// Controllate sempre che non ci siano errori!! Questa operazione è tra le più importanti per la sicurezza del software!!
if(testozeri=malloc(sizeof(char)*(lunghezzastringa+zeri+1)))==NULL){
printf("\n C'è stato un errore nella allocazione della memoria\n");
printf("\n Impossibile aggiungere zeri!\n");
return NULL;
}

  for(i=0;i<lunghezzastringa;i++)
      testozeri[i] = passwd[i]; 
// scusate se non ho usato parentesi comunque questo for esegue solo questa operazione!
 for(j=0;j<zeri;j++){
	testozeri[i]=(char)12;
 }
/* ATTENZIONE: Vogliamo una stringa, quindi il carattere finale deve essere sempre '\0' 
 Nel l'ultimo ciclo del precedente for l'ultima cosa che faccio è aumentare l'indice 'i' perciò il carattere finale lo inserisco nel posto dopo l'ultimo carattere!*/ 
testozeri[i]='\0'; 
return testozeri 
} 

Il codice è semplice: si dichiarano le variabili: i e j servono per i contatori (i cicli for), lunghezzastringa conterrà il numero di caratteri della stringa, dimensione il numero di caratteri del testo da cifrare.

La variabile ‘contatore’ non fa altro che memorizzare la lunghezza stringa e aumentare il suo valore di uno per ogni ciclo del while.

Il while incrementa contatore finché il modulo tra il suo valore e quello di dimensione non è diverso da zero (Ovvero finché il numero di caratteri del testo da cifrare non è multiplo della password.

Per trovare il numero di zeri da aggiungere, basterà sottrarre al valore contato la lunghezza della stringa. L’istruzione successiva alloca lo spazio di memoria utile per memorizzare il testo con gli zeri finali. Le dimensioni di questo spazio sono la dimensione in byte occupata da un carattere (1 byte) per il numero di caratteri da memorizzare più il numero di zeri da aggiungere piu il carattere di l’interruzione riga (‘\0’).

Se non si riesce ad allocare questo spazio viene visualizzato un messaggio di errore e la funzione viene interrotta restituendo valore NULL. Un controllo esterno con un if si preoccupa di verificare che la malloc() non abbia restituito il valore NULL. Dopo di che i cicli successivi copiano la stringa carattere per carattere e aggiungono gli zeri. L’ultima istruzione prima del return() non fa altro che aggiungere il carattere di chiusura stringa. Return() ritorna il testo con gli zeri.

Bene, è arrivato il momento di addentrarci nel vero processo di cifratura. Le funzioni che gestiscono tale processo sono 2: Prima di tutto la funzione Xor() si occupa di cifrare il singolo carattere utilizzando la chiave, la seconda funzione richiama la prima più volte per cifrare l’intero testo.

La funzione Xor() è questa:

char Xor(char carattere, char chiave){

   char criptato
   int i=0;
 
   if((carattere^Key(chiave))>' ' && (carattere^Key(chiave)<'~')){
        criptato=carattere^Key(chiave);
   } else {
   while(i<=86 && (carattere^Key(i)<' ') && (carattere^Key(i)>'~')){
        i++;
   }
   if(i>86){
        criptato=carattere;
   } else {
        criptato=carattere^Key(chiave);
   }
 }
 return criptato;
}

che prende come argomento il carattere da cifrare, e la chiave, ovvero il carattere della password che si darà in pasto alla funzione Key. Come si vede il cifrario cifra tramite lo Xor con un carattere preso a caso tramite la funzione Key, come due rotori di enigma che posizionati permettono di cifrare il testo (L’unica differenza è che qui la lettera associata al carattere della password tramite la funzione key è statica ogni volta che avviamo il programma).

Nel primo if controllo che il carattere ottenuto dalla cifratura non sia un carattere speciale per evitare problemi con la lettura e la scrittura della stringa.
Se non lo è, cifro tramite Xor il carattere, se invece lo è, il while successivo scorre la stringa di caratteri da utilizzare come chiavi finché non ne trovo uno con il quale la cifratura restituisca un carattere scrivibile.
Se i è maggiore di 86, che è la posizione dell’ultimo carattere, allora significa che non ne ha trovati quindi copio il carattere originale senza cifrarlo.

Implementiamo lo Xor!!

Se i non ha superato il valore 86 e sono uscito dal while, significa invece che è stato trovato il carattere che permettere di ottenere come risultato dello Xor un carattere scrivibile, quindi cifro utilizzando quel carattere.

char *Cifra_Testo(char *testodacifrare, char *passwd) {

int dimensione=0,i=0,count=0,lunghezzapasswd=0;
char *testo_cifrato=NULL;
testozeri=NULL;

lunghezzapasswd=ContaCaratteri(passwd);
testozeri=Aggiungi_Zeri(testodacifrare,lunghezzapasswd);
dimensione=ContaCaratteri(testozeri);
testo_cifrato=malloc(sizeof(char)*(dimensione+1));

while((i)&lt;=(dimensione-lunghezzapasswd)){
for(count=0;count&amp;amp;lt;lunghezzapasswd;count++){
testo_cifrato[i+count]=Xor(testozeri[i+count],passwd[count]);
}
i+=(count);
}
free(testozeri);
testo_cifrato[dimensione+1]='\0';
return testo_cifrato;
}

Nella funzione è racchiuso lo scopo di tutto il lavoro effettuato fino ad ora.
La variabile dimensione contiene il valore intero di caratteri del testo da cifrare, i serve da contatore.
Per quanto riguarda ‘count’, anche esso viene utilizzato da contatore ma in un modo particolare.
‘Testocifrato’ conterrà il risultato della nostra cifratura mentre testo zeri conterrà il nostro testo con l’aggiunta degli zeri tramite la funzione Aggiungi_Zeri().

Funzionamento

La funzione conta i caratteri della password e invia il valore come argomento alla funzione Aggiungi_Zeri() che aggiungerà il giusto numero di zeri da aggiungere alla fine del testo in modo da rendere il numero di caratteri che lo compone un multiplo della password.

Successivamente vengono quindi contati il numero di caratteri che compone il nostro testo con l’aggiunta degli zeri e viene allocata la giusta quantità di memoria, tramite la malloc(), affibbiandole l’etichetta ‘testo_cifrato’, che punterà al primo byte dello spazio di memoria allocato. “Puntare” significa, parlando a livello di linguaggio macchina, funzionare da etichettà per dare un nome più tangibile a tale zona di memoria.

La cifratura vera e propria viene implementata tramite ciclo while.
La condizione per cui tale ciclo non venga interrotto è che i sia minore o uguale della dimensione del testo da cifrare meno la dimensione in caratteri della password.
Questo perché il testo viene cifrato utilizzando i come contatore di cicli; ad ogni ciclo viene cifrato un numero di caratteri pari al numero di caratteri di cui è composta la password. Questo viene fatto tramite la variabile count che tiene conto della lunghezza della password.
Ad ogni ciclo si incrementa la i del valore della variabile count e la stessa count tiene conto di quale carattere della password viene utilizzato per la cifratura.
Faccio un semplice esempio: i caratteri del testo vengono selezionati dal valore assunto da ‘i+count’ per cui se i è 0 (prima esecuzione del ciclo) vengono cifrati tutti i caratteri da 0 al numero dei caratteri della password (meno 1 poiché si inizia a contare da 0).

Al secondo ciclo, i assumerà il valore di lunghezzapasswd, per cui la variabile i+count assumerà
tutti i valori da lunghezzapassword al valore lunghezzapasswd+(lunghezzapasswd-1).

Simone Sante Ruffo
Diplomato al liceo scientifico, si è laureato in ingegneria informatica e delle telecomunicazioni e sta proseguendo ora gli studi in Ingegneria Elettronica per prendersi la laurea magistrale. Appassionato di informatica, telecomunicazioni ed elettronica gli piace studiare, conoscere, progettare e risolvere problemi
http://simonesanteruffo.it

Lascia un commento

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.

Top