Il cifrario di Vigenère in PHP
- Ottobre 21, 2010
- by
- Donatantonio
In due articoli precedenti abbiamo analizzato, grazie a PHP, due algoritmi di cifratura: Cesare e Blowfish.
Il primo al solo scopo didattico-storico, mentre il secondo pienamente utilizzabile all’interno delle nostre applicazioni, viste le sue potenzialità e il grado di sicurezza che fornisce.
Il cifrario di Vigenère è il più semplice dei cifrari polialfabetici. Si basa sull’uso di un versetto (chiave) per controllare l’alternanza degli alfabeti di sostituzione.
Il metodo si può considerare una generalizzazione del cifrario di Cesare; invece di spostare sempre dello stesso numero di posti la lettera da cifrare, questa viene spostata di un numero di posti variabile ma ripetuto, determinato in base ad una parola chiave e da scrivere ripetutamente sotto il messaggio, carattere per carattere:
testo in chiaro: | CIAO MAMMA CIAO |
chiave: | CHIA VECHI AVEC |
testo cifrato: | EPIO HEOTI CDEQ |
Il testo cifrato si ottiene spostando la lettera chiara di un numero fisso di caratteri, pari al numero ordinale della lettera corrispondente della chiave.
Per semplificare la cifratura/decifratura Vigenère propose una matrice quadrata (26 X 26) composta da alfabeti ordinati e spostati.
Nel codice che andremo a sviluppare utilizzeremo questa versione “classica” dell’algoritmo, difatti realizzeremo la matrice e la cifratura/decifratura verrà eseguita su di essa.
In fondo all’articolo è possibile provare e scaricare il codice completo.
Passiamo quindi al codice della classe che chiameremo vigenere.php.
La classe si comporrà dei seguenti metodi:
- Costruttore per la realizzazione della matrice (tavola di Vigenère)
- Metodo di cifratura
- Metodo di decifratura
- Metodo che stampa a video la tavola di Vigenère
Ecco il codice PHP:
<?php class Vigenere{ var $alfabeto = array('A','B','C','D','E','F','G','H','I','J','K','L','M','N', 'O','P','Q','R','S','T','U','V','W','X','Y','Z'); var $matrice; var $chiave; // Il costruttore imposta la chiave e realizza la matrice function Vigenere($chiave){ $this->chiave = str_replace(array(" ",".",",",";"),"", $chiave); $app1 = array(); $app2 = array(); $alfabeto_app = array(); for($i=0; $i<26; $i++){ $k=0; $app1 = array_slice($this->alfabeto,0,$i); $app2 = array_slice($this->alfabeto,$i); $this->matrice[$i] = array_merge($app2,$app1); } } // Metodo che stampa la matrice function stampaTavola(){ echo "<table border='1' cellpadding='1' cellspacing='0'> <tr><td rowspan='27' width='50px' align='center'>T<br>E<br>S<br>T<br>O<br> <br>I<br>N<br> <br>C<br>H<br>I<br>A<br>R<br>O<br></td><td colspan='26' align='center' height='50px'>CHIAVE</td></tr>"; for($i=0; $i<26; $i++){ echo "<tr>"; for($j=0; $j<26; $j++){ echo "<td align='center'>".$this->matrice[$i][$j]."</td>"; } echo "</tr>"; } echo "</table>"; } // Metodo per la cifratura function cifratura($testo){ $txt_cifrato = ""; $l_chiave = strlen($this->chiave); $k = 0; for($i=0; $i<strlen($testo); $i++){ $chr_t = substr($testo,$i,1); $chr_c = substr($this->chiave,$k,1); if(in_array(strtoupper($chr_t),$this->alfabeto) && in_array(strtoupper($chr_c),$this->alfabeto)){ $x = array_search(strtoupper($chr_t),$this->alfabeto); $y = array_search(strtoupper($chr_c),$this->alfabeto); $txt_cifrato = $txt_cifrato.$this->matrice[$x][$y]; $k++; }else{ $txt_cifrato = $txt_cifrato.strtoupper($chr_t); } if($k==$l_chiave) $k = 0; } return $txt_cifrato; } // Metodo per la decifratura function decifratura($testo){ $txt_decifrato = ""; $l_chiave = strlen($this->chiave); $k = 0; for($i=0; $i<strlen($testo); $i++){ $chr_t = substr($testo,$i,1); $chr_c = substr($this->chiave,$k,1); if(in_array(strtoupper($chr_t),$this->alfabeto) && in_array(strtoupper($chr_c),$this->alfabeto)){ $colonna = array_search(strtoupper($chr_c),$this->alfabeto); $riga = 0; for($c=0; $c<26; $c++){ if($this->matrice[$c][$colonna]==$chr_t){ $riga = $c; break; } } $txt_decifrato = $txt_decifrato.$this->matrice[$riga][0]; $k++; }else{ $txt_decifrato = $txt_decifrato.$chr_t; } if($k==$l_chiave) $k = 0; } return $txt_decifrato; } } ?>
Utilizzando un array contenete l’alfabeto, realizzeremo la matrice semplicemente tagliando ad ogni riga l’alfabeto in due parti, grazie alla funzione array_slice, per poi ricomporlo in maniera inversa.
Grazie a questa matrice i metodi cifratura e decifratura risultano abbastanza semplici:
– cicliamo lettera per lettera sul testo in chiaro e sulla chiave
– per ogni coppia di lettere (chiaro-chiave) verifichiamo le posizioni nell’alfabeto
– le coordinate x e y ottenute individueranno la lettera cifrata nella matrice
Il cuore del codice di cifratura è composto essenzialmente dalle tre righe:
$x = array_search(strtoupper($chr_t),$this->alfabeto); $y = array_search(strtoupper($chr_c),$this->alfabeto); $txt_cifrato = $txt_cifrato.$this->matrice[$x][$y];
Per la decifratura il procedimento è lo stesso, richiede solo una ricerca differente basata sulle colonne identificate dalle lettere che compongono la chiave.
Infine è presente un metodo denominato stampaTavola che visualizza a video la matrice favorendo la verifica manuale del processo di cifratura/decifratura.
La classe va così richiamata:
<?php require_once 'vigenere.php'; $vigenere = new Vigenere($chiave); $vigenere->stampaTavola(); $txt_cifrato = $vigenere->cifratura($testo); $txt_decifrato = $vigenere->decifratura($txt_cifrato); ?>
All’interno della cartella contenente il codice completo sono presenti i seguenti file:
- vigenere.php (la classe vista sopra)
- test.php (lo script che effettua la cifratura/decifratura)
- index.html (un form per il test di coppie chiave-testo in chiaro)
Cliccando qui è possibile vedere in azione il codice.
Cliccando qui è possibile scaricare il codice.
1 Comment
Il disco cifrante di Alberti in PHP | Fabio Donatantonio
18th Lug 2011 - 23:21[…] il cifrario di Cesare e Vigenère continuiamo l’excursus sulle tecniche di cifratura che hanno contraddistinto la storia e […]