Il disco cifrante di Alberti in PHP
- Ottobre 30, 2010
- by
- Donatantonio
Dopo il cifrario di Cesare e Vigenère continuiamo l’excursus sulle tecniche di cifratura che hanno contraddistinto la storia e l’evoluzione di questa disciplina.
Leon Battista Alberti, vissuto a metà del ‘400, fu una delle figure artistiche più poliedriche del Rinascimento. Scrittore, architetto e matematico, fu anche un celebrato crittografo per gli standard della sua epoca, ed inventò un metodo per generare messaggi criptati con l’aiuto di un apparecchio, il disco cifrante.
Il disco cifrante è il primo sistema di cifratura polialfabetica, ancor prima del “troppo” famoso cifrario di Vigenère rispetto cui è estremamente più potente.
L’apparecchio si compone di due dischi concentrici, rotanti uno rispetto all’altro, contenenti un alfabeto ordinato per il chiaro (testo da cifrare) e un alfabeto mischiato per il cifrato (testo risultante). Permette la sostituzione polialfabetica con periodo irregolare. Lo scorrimento degli alfabeti avviene per mezzo di lettere chiave inserite nel corpo del crittogramma.
Nonostante la potenza di questo algoritmo il suo utilizzo è molto semplice e intuitivo. Prendiamo ad esempio in considerazione i due alfabeti:
Disco esterno | 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 |
Disco interno | t | d | v | h | a | r | s | z | c | p | e | w | i | x | g | u | k | m | b | l | y | f | j | o | n | q |
Il mittente e il destinatario si accordano su un indice di cifratura che dovrà rimanere segreto. Quest’indice è essenzialmente una lettera dell’alfabeto ordinato.
In base a questo indice si effettuerà la cifratura/decifratura, sottoponendo di volta in volta una lettera del disco interno e mobile.
In relazione agli alfabeti visti sopra, se ad esempio la lettera “indice” fosse la “A” e si decidesse di cifrare con lettera “chiave” uguale a “s” si otterrebbe il seguente disco cifrante (abbiamo ruotato di n posizioni l’alfabeto mischiato):
Disco esterno | 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 |
Disco interno | s | z | c | p | e | w | i | x | g | u | k | m | b | l | y | f | j | o | n | q | t | d | v | h | a | r |
A questo punto cifriamo la frase: CIAO MAMMA
CIAO MAMMA = Scgsy bsbbs
Sostituendo a ciascuna lettera in chiaro del disco superiore, la sottostante lettera cifrata del disco inferiore si ottiene il testo cifrato. Da notare la prima lettera in maiuscolo (la R) che indica appunto la lettera chiave di cifratura utile al destinatario per interpretare il messaggio.
Dopo aver cifrato alcune lettere si inserisce una nuova lettera maiuscola che indica il cambio delle lettera chiave, ruotando appunto il disco mobile e ottenendo una nuova cifratura.
Il cifrario di Alberti è quindi a tutti gli effetti una sostituzione polialfabetica con alfabeti mischiati cambiati saltuariamente in modo segreto.
Veniamo ora al nostro codice PHP che ci permette di implementare tale cifrario.
Realizzeremo una classe denominata Alberti che farà uso di due array contenenti il primo l’alfabeto ordinato e in maiuscolo e il secondo un alfabeto mischiato in minuscolo.
Nel costruttore della classe acquisiamo due lettera:
- La lettera indice dell’alfabeto ordinato
- La lettera chiave dell’alfabeto mischiato
Infine forniremo tre metodi:
- Stampa del disco ottenuto
- Cifratura
- Decifratura
In fondo all’articolo è possibile provare e scaricare il codice completo.
Vediamo il codice della classe:
<?php class Alberti{ var $fisso = 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 $disco = array('t','d','v','h','a','r','s','z','c','p','e','w', 'i','x','g','u','k','m','b','l','y','f','j','o','n','q'); var $posizione; function Alberti($base, $partenza){ // Scegliamo la lettera di base che andrà in posizione 0 $this->posizione = array_search(strtoupper($base),$this->fisso); $app1 = array_slice($this->fisso,0,$this->posizione); $app2 = array_slice($this->fisso,$this->posizione); $this->fisso = array_merge($app2,$app1); // Ruotiamo il disco interno in base alla lettera di partenza che andrà in posizione 0 $rotazione = array_search(strtolower($partenza),$this->disco); $app1 = array_slice($this->disco,0,$rotazione); $app2 = array_slice($this->disco,$rotazione); $this->disco = array_merge($app2,$app1); } function stampa(){ echo "<table border='1'><tr><td>Disco esterno</td>"; for($i=0; $i<count($this->fisso); $i++){ echo "<td>".$this->fisso[$i]."</td>"; } echo "</tr><tr><td>Disco interno</td>"; for($i=0; $i<count($this->disco); $i++){ echo "<td>".$this->disco[$i]."</td>"; } echo "</tr></table>"; } function cifratura($testo){ $txt_cifrato = strtoupper($this->disco[0]).""; for($i=0; $i<strlen($testo); $i++){ $chr_t = substr($testo,$i,1); if(in_array(strtoupper($chr_t),$this->fisso)){ $pos = array_search(strtoupper($chr_t),$this->fisso); $txt_cifrato = $txt_cifrato.$this->disco[$pos]; }else{ $txt_cifrato = $txt_cifrato.$chr_t; } } return $txt_cifrato; } function decifratura($cifrato){ $txt_chiaro = ""; for($i=1; $i<strlen($cifrato); $i++){ $chr_t = substr($cifrato,$i,1); if(in_array(strtolower($chr_t),$this->disco)){ $pos = array_search(strtolower($chr_t),$this->disco); $txt_chiaro = $txt_chiaro.$this->fisso[$pos]; }else{ $txt_chiaro = $txt_chiaro.$chr_t; } } return $txt_chiaro; } } ?>
L’alfabeto del disco mobile (quello mischiato) è stato scelto in modo del tutto arbitrario, è possibile modificarlo per ottenere cifrature sempre diverse.
Nel costruttore, in relazione alle due lettere acquisite, vengono ruotati gli alfabeti in modo tale da far coincidere in posizione 0 (zero) le due lettere scelte per la cifratura.
A tale scopo viene utilizzato una funzione php molto utile, array_slice, che ci permette di tagliare un array ottenendo un sottoarray:
$app1 = array_slice($this->disco,0,$rotazione); $app2 = array_slice($this->disco,$rotazione);
Una volta riuniti i due sottoarray in ordine inverso si ottine la rotazione dell’alfabeto.
Grazie a questi due array la cifratura e decifratura si limita ad una sostituzione di lettere in base alla loro posizione.
La sintassi per utilizzare questa classe è la seguente:
<?php require_once 'alberti.php'; $alberti = new Alberti($lettera_indice,$lettera_chiave); $alberti->stampa(); $txt_cifrato = $alberti->cifratura($testo); $txt_decifrato = $alberti->decifratura($txt_cifrato); ?>
Alcune considerazioni finali sono d’obbligo; l’algoritmo implementato non tiene conto di alcune varianti presenti nella cifratura di Alberti, riguardanti ad esempio le lettere doppie e i numeri.
Per ottenere una sostituzione polialfabetica basta poi invocare la classe più volte cambiando di conseguenza la lettera chiave dell’alfabeto mischiato.
All’interno della cartella contenente il codice completo sono presenti i seguenti file:
- alberti.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.