Enigma e la “bomba” di Turing Una storia contemporanea di
by user
Comments
Transcript
Enigma e la “bomba” di Turing Una storia contemporanea di
Enigma e la “bomba” di Turing Una storia contemporanea di crittografia e crittoanalisi Francesco Burato 1 2 Indice 1 2 3 3.1 3.2 4 4.1 4.2 4.3 5 5.1 5.2 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Enigma: la prima macchina per cifrare elettromeccanica. . . . . . Enigma: versione informatica della macchina. . . . . . . . . . . . Scelte strategiche di realizzazione. . . . . . . . . . . . . . . . . . Specifiche di oggetti e metodi . . . . . . . . . . . . . . . . . . . . 3.2.1 Interfaccia Rotore . . . . . . . . . . . . . . . . . . . . . . 3.2.2 Classe Scambiatore . . . . . . . . . . . . . . . . . . . . . . 3.2.3 Classe Riflessore . . . . . . . . . . . . . . . . . . . . . . . 3.2.4 Classe ClickEvent ed interfaccia ClickListener. . . . . . . 3.2.5 Classe PannelloPrese . . . . . . . . . . . . . . . . . . . . . 3.2.6 Classe Enigma . . . . . . . . . . . . . . . . . . . . . . . . 3.2.7 Classe EnigmaSimulator . . . . . . . . . . . . . . . . . . . La “Bomba” di Turing . . . . . . . . . . . . . . . . . . . . . . . . Sinossi del primo tentativo di crittoanalisi: la “bomba” di Rejewski Bletchley park . . . . . . . . . . . . . . . . . . . . . . . . . . . . La “bomba” di Turing . . . . . . . . . . . . . . . . . . . . . . . . La “Bomba” di Turing: versione Informatica . . . . . . . . . . . . Considerazioni sulla simulazione . . . . . . . . . . . . . . . . . . Specifiche di oggetti e metodi . . . . . . . . . . . . . . . . . . . . 5.2.1 Classe EnigmaForAnalysis . . . . . . . . . . . . . . . . . . 5.2.2 Classe BadCribException . . . . . . . . . . . . . . . . . . 5.2.3 Classe CribNode . . . . . . . . . . . . . . . . . . . . . . . 5.2.4 Classe CribNodeList . . . . . . . . . . . . . . . . . . . . . 5.2.5 Classe CribTree . . . . . . . . . . . . . . . . . . . . . . . . 5.2.6 Classe Bomb . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.7 Classe BombRunner . . . . . . . . . . . . . . . . . . . . . 5.2.8 Classe AlanTuringBombs . . . . . . . . . . . . . . . . . . 5.2.9 Classe AlanTuringBombSimulator . . . . . . . . . . . . . 3 3 11 11 12 12 12 14 14 15 16 17 19 19 21 22 28 28 29 29 30 30 31 31 32 33 33 34 1 Introduzione 1 3 Introduzione Per migliaia di anni, re, regine e generali hanno avuto bisogno di comunicazioni efficienti per governare i loro paesi e comandare i loro eserciti. Nel contempo, essi compresero quali conseguenze avrebbe avuto la caduta dei loro messaggi in mani ostili: informazioni preziose sarebbero state a disposizione delle nazioni rivali e degli eserciti nemici. Fu il pericolo dell’intercettazione da parte degli avversari a promuovere lo sviluppo di codici e cifre, tecniche di alterazione del messaggio destinate a renderlo comprensibile solo alle persone autorizzate. Il bisogno di segretezza ha indotto le nazioni a creare segreterie alle cifre e dipartimenti di crittografia. È stato loro compito garantire la sicurezza delle comunicazioni, escogitando e impiegando i migliori sistemi di scrittura segreta. Nello stesso tempo, i decrittatori, o crittoanalisti, hanno tentato di far breccia in quei sistemi e carpire i dati che custodivano. Crittografi e decrittatori sono cercatori di significati, alchimisti votati alla trasmutazione di astruse serie di segni in parole dotate di senso. La storia dei codici è la storia dell’antica, secolare battaglia tra inventori e solutori di scritture segrete; una corsa agli armamenti intellettuale il cui impatto sulle vicende umane e sulla tecnologia è stato profondo. La lunga battaglia tra inventori e solutori di codici ha prodotto importanti progressi scientifici. Gl’inventori hanno creato codici sempre più resistenti mentre i solutori, per farvi breccia, hanno escogitato metodi sempre più sofisticati. Nello sforzo di tutelare e, rispettivamente, violare la segretezza, gli opposti schieramenti hanno attinto a un’ampia gamma di scienze e specializzazioni, dalla matematica alla linguistica, dalla teoria dell’informazione alla fisica quantistica. A loro volta, inventori e solutori di codici hanno arricchito queste discipline, e il loro lavoro ha accelerato il progresso tecnologico, come è dimostrato nel caso dei calcolatori. Sebbene la storia sia ricca di circostanze in cui la decifrazione di un messaggio (o la resistenza del codice usato per cifrarlo) ha deciso l’esito di una battaglia o il destino di una testa coronata, l’esempio lampante di come la crittografia e la crittoanalisi abbiano determinato le sorti dell’umanità intera si ha nel XX secolo con le vicende legate alla macchina Enigma, la famigerata cifratrice meccanica in dotazione all’esercito tedesco durante la Seconda Guerra Mondiale. La violazione dei codici prodotti da Enigma è stato un passo fondamentale affinché la guerra terminasse con la vittoria degli Alleati in quanto l’intelligence prodotta dai crittoanalisti inglesi ha determinato le sorti di battaglie fondamentalti come quella dell’Atlantico. 2 Enigma: la prima macchina per cifrare elettromeccanica. Nel 1918 l’inventore tedesco Arthur Scherbius e il fidato amico Richard Ritter fondarono la Scherbius & Ritter, una società innovativa che non disdegnava di occuparsi dei prodotti più diversi, dalle turbine ai guanciali riscaldati. Scherbius si era riservato la ricerca e lo sviluppo, ed era sempre a caccia di nuove opportunità. Uno dei suoi progetti era rivoluzionare l’antiquato modus operandi della crittografia mandando in pensione carta e penna, e sostituendole con quanto di meglio la tecnica del ventesimo secolo avesse da offrire. 2 Enigma: la prima macchina per cifrare elettromeccanica. 4 Avendo studiato ingegneria elettrica ad Hannover e Monaco, egli mise appunto un dispositivo crittografico che in sostanza era una versione elettromeccanica del disco cifrante di Leon Battista Alberti, famoso per essre stato la prima macchina per cifrare mai realizzata. La sua invenzione, che fu chiamata Enigma, sarebbe passata alla storia come uno fra i più temibili sistemi crittografici mai realizzati. La macchina di Scherbius consisteva di diversi ingegnosi elementi da lui combinati in un potente e sofisticato dispositivo per la produzione di scritture segrete. Tuttavia, se smontiamo concettualmente la macchina e la ricostruiamo un elemento per volta, i principi del suo funzionamento ap- Fig. 1: Esempio di disco cifrante di Leon pariranno evidenti. La versione base Battista Alberti del congegno di Scherbius consisteva in tre componenti collegati da fili elettrici: una tastiera per immettere le lettere del testo chiaro; un’unità scambiatrice che cifra la lettera trasformandola nel corrispondente elelmento del crittogramma; e un visore con varie lampadine, che accendendosi indicano la lettera da inserire nel crittogramma. In figura 2 è riportato uno schema semplificato del congegno, basato per semplicità su un alfabeto di sole sei lettere. Per generare il crittogramma, l’operatore preme il tasto corrispondente alla lettera da crittare; l’impulso elettrico raggiunge l’unità scambiatrice, e dopo esser stato elaborato va ad illuminare il visore in modo corrispondente alla lettera crittata. Fig. 2: Versione semplificata della macchina Enigma con un alfabeto cifrate di sei lettere. L’elemento più importante di enigma è lo scambiatore. Digitando b sulla sinistra, la corrente entra nello scambiatore, segure il percorso dei fili elettrici ed emerge in modo da illuminare la lettera A. In breve, b è crittata come A. La tabella a destra riassume il modo in ciascuna lettera è cifrata. Lo scambiatore, uno spesso disco di gomma attraversato da una complessa rete di fili, è la parte più importante della macchina. I fili elettrici provenienti dalla tastiera entrano nello scambiatore in sei punti, seguono un percorso carat- 2 Enigma: la prima macchina per cifrare elettromeccanica. 5 terizzato da vari gomiti, e infine emergono dalla parte opposta in altri sei punti. I circuiti interni dello scambiatore determinano il modo in cui un elemento del testo chiaro è crittato. Con lo schema di base indicato in figura 2 nella tabella di conversione è possibile realizzare in sostanza una semplice cifratura per sostituzione monoalfabetica ovvero una cifratura in cui ciascuna lettera è sostituita con un’altra. Il passo successivo dell’idea di Scherbius consiste nel far ruotare automaticamente il disco scambiatore di un sesto di giro (o di un ventiseiesimo di giro nel caso di un alfabeto completo di 26 lettere) dopo la cifratura di ogni lettera. In figura 3 è riportato un esempio di come lo scambiatore di figura 2, girato di un sesto di giro ad ogni uso dello scambiatore, produca testi cifrati diversi. Fig. 3: Ogni volta che una lettera è digitata tramite la tastiera e crittata, lo scambiatore ruota di un posto. In (a) lo scambiatore critta b come A, ma in (b) il nuovo orientamento fa si che b sia crittata come C. In (c), essendo ruotato di un altro posto, lo scambiatore cifra b come E. Dopo la sostituzione di altre 4 lettere, e dopo aver ruotato di altri 4 posti, lo scambiatore riprende la configurazione iniziale. Lo scambiatore rotante è la caratteristica più importante del progetto di Scherbius. Tuttavia, così com’è il congegno ha un punto debole evidente: dopo sei pressioni consecutive di qualunque tasto, il disco torna alla posizione iniziale, e se si continuasse a premere lo stesso tasto, lo schema di cifratura si ripeterebbe tale e quale. In generale, i crittografi temono ogni forma di ripetizione, perché ripetizione significa regolarità e struttura del crittogramma, sinonimo di cifra- 2 Enigma: la prima macchina per cifrare elettromeccanica. 6 tura debole. Il problema può essere corretto in misura notevole introducendo un nuovo scambiatore. Nella figura 4(a) il primo disco è sul punto di far avanzare il secondo. Dopo aver battuto sulla tastiera e crittato una lettera, passiamo alla figura 4(b), in cui il primo disco è avanzato di un posto e il secondo, spinto dal precedente, è anch’esso avanzato di un posto. Battuta e crittata un’altra lettera, passiamo alla figura 4(c) in cui di nuovo il primo disco è avanzato di un posto; questa volta però il secondo è rimasto fermo; tornerà ad avanzare quando il primo avrà completato un giro, dopo aver crittato quindi altre 5 lettere. Risulta quindi evidente che il meccanismo illustrato è lo stesso che viene attuato nei contachilometri: con il passaggio del disco delle unità dalla cifra 9 alla cifra 0 il disco delle decine avanza di un posto, e lo stesso avviene anche per tutti gli altri dischi. L’aggiunta del secondo scambiatore comporta il vantaggio che lo schema di cifratura non si ripete finchè il secondo scambiatore non è tornato al punto di partenza, il che richiede sei giri completi del primo scambiatore ovvero la cifratura di 6x6 lettere. In altre parole, due dischi con sei posizioni ciascuno equivalgono ad una sostituzione monoalfabetica del tipo descritto in precedenza che prevede l’uso di 36 diversi alfabeti cifranti detta, per questo motivo, cifratura polialfabetica, dello stesso tipo di quella che veniva realizzata con il disco di Alberti. Se invece del nostro alfabeto semplificato fosse adoperato un alfabeto completo di 26 lettere, l’unità cifratrice commuterebbe in tutto 26x26, cioè 676, alfabeti cifranti. A questo punto dovrebbe essere chiaro che combinando i dischi scambiatori, detti anche rotori, è possibile costruire una macchina per cifrare molto sofisticata, capace di utilizzare un enorme numero di alfabeti cifranti passando continuamente da uno ad un altro di essi. L’operatore batte una lettera particolare e, in conformità con l’assetto dei rotori, la lettera è crittata in base a una delle centinaia di alfabeti cifranti disponibili. Subito dopo l’assetto dei rotori cambia, cosicché la lettera successiva sarà crittata in base ad un altro alfabeto cifrante. Oltretutto, ogni passo è eseguito con estrema precisione e rapidità, grazie ai moviementi automatici dei rotori e alla velocità della corrente elettrica. Prima di esporre nei particolari in che modo Scherbius pensava che la sua macchina sarebbe stata usata, ci sono altri due elementi molto importanti riprodotti in figura 5. Innanzittutto, per una sicurezza ancora maggiore, il modello di base della sua macchina impiegava un terzo rotore. Poiché Enigma utilizzava alfabeti completi di 26 caratteri, essa disponeva di 26x26x26 = 17.576 procedure di sostituzione diverse. Inoltre, l’inventore aggiunse un riflessore. Il riflessore era simile allo scambiatore, consistendo in un disco di gomma con circuiti interni, ma era diverso sia perché non ruotava, sia perché i fili che entravano da un lato uscivano dallo stesso lato. Col riflessore installato, quando l’operatore digitava una lettera il segnale elettrico attraversava i tre scambiatori, raggiungeva il riflessore ed era rimandato indietro. Perciò passava di nuovo dagli scambiatori, ma lungo un percorso differente. Per esempio, in base all’assetto mostrato in figura 5 la pressione del tasto b avrebbe inviato un impulso elettrico attraverso i rotori fino al riflessore. Da qui, l’impulso sarebbe tornato indietro lungo i collegamenti e avrebbe raggiunto la lettera D. Naturalmente il segnale non sarebbe emerso dalla tastiera, come potrebbe sembrare dalla figura 5, ma avrebbe raggiunto le lampadine del visore. A prima vista il riflessore sembra un’aggiunta inutile poiché, essendo statico, non fa aumentare il numero di alfabeti cifranti. 2 Enigma: la prima macchina per cifrare elettromeccanica. 7 Fig. 4: Aggiungendo un altro scambiatore, lo schema di cifratura non si ripete prima che siano sostituite 36 lettere; allora, e solo allora, entrambi gli scambiatori saranno tornati alla posizione iniziale. Per semplificare la figura, gli scambiatori sono rappresentati in forma bidimensionale; invece di ruotare di un posto i collegamenti si spostano verso il basso di un posto. Quando il filo elettrico sembra comparire in fondo allo scambiatore, lo si potrà ritrovare subito sotto l’estremità superiore della figura. In (a), b è crittata come D. Dopo la cifratura, il primo scambiatore ruota di un posto, facendo ruotare di un posto anche il secondo scambiatore - ciò si verifica una volta sola durante la rivoluzione del primo rotore. Il nuovo assetto è mostrato in (b) dove b è crittata come F. Dopo la cifratura, il primo scambiatore ruota di un posto, ma in questo caso il secondo scambiatore mantiene il suo orientamento. Il nuovo assetto è mostrato in (c), dove b è crittata come B. 2 Enigma: la prima macchina per cifrare elettromeccanica. 8 Fig. 5: Il progetto di scherbius del modello base di Enigma includeva una quarto rotore detto riflessore, che costringeva l’impulso elettrico ad attraversare di nuovo gli scambiatori. Ma osservando come la macchina veniva usata per cifrare e decifrare i messaggi, i vantaggi risultano evidenti. Supponiamo che un operatore volesse inviare una comunicazione cifrata. Prima di cominciare egli doveva regolare gli scambiatori, in modo che assumessero la posizione iniziale voluta. Le posizioni possibili erano, come si è spiegato, 17.576; quella prescelta determinava il modo in cui un particolare messaggio sarebbe stato crittato. La macchina Enigma era paragonabile ad un procedimento crittografico generale, cioè ad un algoritmo crittografico. In tal caso, l’assetto iniziale di Enigma forniva ulteriori precisazioni necessarie alla cifratura, ossia equivaleva ad una chiave. Di solito la posizione iniziale era contenuta in un cifrario, che elencava le chiavi da usare di giorno in giorno ed era a disposizione di tutti gli operatori della rete. La distribuzione del cifrario richiedeva tempo e fatica, ma dato che era necessaria solo una chiave al giorno, era sufficiente l’invio di un cifrario contenente 28 chiavi ogni 4 settimane. Una volta regolati i rotori come richiesto dal cifrario, l’operatore poteva iniziare la codifica del messaggio: premeva il tasto corrispondente alla prima lettera, osservava la prima lampadina che si illuminava sullo schermo, e ne prendeva nota. Poi, dopo che il primo rotore era automaticamente passato alla posizione successiva, l’operatore batteva la seconda lettera in cifra e così via. Completato il crittogramma lo progeva al marconista, che lo inviava al destinatario. Per decifrare il crittogramma, il destinatario doveva possedere un’altra macchina Enigma, e un cifrario con l’assetto dei rotori da utilizzare giorno per giorno. Egli regolava la macchina come spiegato dal cifrario, batteva il crittogramma lettera dopo lettera, e annotava i caratteri del testo chiaro, indicati dall’accensione delle lampadine sul visore. In altre parole, mentre il mittenete digitava il testo chiaro per generare il crittogramma, il destinatario digitava il crittogramma per ripristinare il testo chiaro; cifratura e decifrazione comportavano dunque le stesse operazioni. La comodità della decifrazione era merito del riflessore. Nella figura 5 si vede che premendo il tasto b e seguendo il percorso della corrente elettrica, andiamo a D. In modo analogo, premendo il tasto d e seguendo il percorso torniamo a B. La macchina trasforma un carattere in chiaro in un carattere cifrato, e, purché sia nel medesimo assetto, è in grado di trasformare il carattere cifrato 2 Enigma: la prima macchina per cifrare elettromeccanica. 9 nell’originario carattere chiaro. Non si poteva certo escludere che uno o più esemplari di Enigma cadessero in mani ostili, ma in mancanza dei dati sull’assetto iniziale sarebbe stato estremamente difficile violare i crittogrammi generati dal congegno. Senza il cifrario, i crittoanalisti nemici avrebbero dovuto controllare ogni giorno tutte le 17.576 chiavi possibili. Se avessero posseduto uno o più esemplari di Enigma, il loro compito sarebbe stato un po’ più facile: avrebbero dovuto selezionare una assetto, provare a decifrare un frammento di crittogramma e se il risultato fosse stato privo di senso, passare all’assetto successivo. Ammesso di poter controllare un assetto al minuto, e di continuare la prova di giorno e di notte senza interruzione, vagliarli tutti avrebbe richiesto due settimane. Era un discreto livello di sciurezza, ma se il nemico avesse deciso di impiegare dozzine di persone solo a questo scopo, si sarebbero potuti controllare tutti gli assetti in un solo giorno, e in casi fortunati la chiave avrebbe potuto essere scoperta in qualche ora. Perciò Scherbius decise di accrescere l’affidabilità della sua invenzione aumentando il numero di assetti, cioè di chiavi possibili. Naturalmente avrebbe potuto aggiungere un altro rotore, aumentando le chiavi di 26 volte; preferì invece inserire due nuove caratteristiche. Innanzitutto, rese i rotori removibili e sostituibili. Per esempio, il primo e il terzo rotore potevano scambiarsi i posti. Siccome i rotori erano diversi, e diversi erano i movimenti che compivano durante la cifratura, quet’ultima era influenzata dalla posizione reciproca dei rotori. Dati tre elementi intercambiabili, essi possono essere combinati in sei modi differenti; perciò questo accorgimento aumentava il numero di chiavi di un fattore pari a 6. La seconda caratteristica era l’inserimento di un pannello a prese multiple tra la tastiera ed il primo rotore. Il pannello permetteva al mittente di inserire alcuni cavi muniti di spinotti, che avevano l’effetto di scambiare due lettere prima della loro immissione nel rotore. Per esempio un cavo poteva essere usato per collegare le prese b e a del pannello, cosicché quando il crittografo avesse deciso di crittare b, giunto ai rotori il segnale elettrico avrebbe seguito il percorso proprio della a, e viceversa. L’operatore di Enigma disponeva di sei cavi, che gli davano la possibilità di scambiare sei coppie di lettere. Le altre quattordici lettere restavano non collegate e non scambiate. La figura 6 mostra lo schema della macchina con il pannello a prese multiple in funzione. Poiché il diagramma si riferisce ad un alfabeto semplificato di 6 lettere, sono state scambiate la b e la a. C’è un’altra caratteristica del progetto di Scherbius, il cosiddetto anello che che ancora non è stata menzionato. Anche se l’anello ha una certa influenza sulla cifratura, è l’aspetto meno significativo della cifratrice, e si è ritenuto di poterlo ignorare, in questa discussione così come anche nel progetto di simulazione. Ora che gli elementi principali del dispositivo di Scherbius sono stati descritti, è possibile calcolare il numero di chiavi che esso poteva impiegare. Tale numero disponeva dalle caratteristiche del pannello, dei singoli rotori, e dell’unità cifratrice formata da tre rotori. La lista qui sotto elenca le variabili del dispositivo e il numero di possibilità create da ogni variabile. Scambiatori (detti anche rotori): ognuno dei tre dischi rotanti poteva orientarsi in 26 modi nel piano perpendicolare al suo asse di rotazione. Di conseguenza, erano ammesse 26 x 26 x 26 = 17.576 combinazioni di orientamenti. 2 Enigma: la prima macchina per cifrare elettromeccanica. 10 Fig. 6: Il pannello a prese multiple era interposto tra la tastiera e gli scambiatori. Inserendo gli appositi cavetti era possibile scambiare due lettere. Così, in questo caso, lo scambio riguarda b e a. Durante la cifratura di b, la corrente segue il percorso che normalmente caratterizza la cifratura di a. Nel caso di una macchina Enigma reale, a 26 lettere, l’operatore disponeva di almeno sei cavi e poteva scambiare almeno sei coppie di lettere simultaneamente. Unità-cifratrice: i tre scambiatori (1,2 e 3) potevano essere inseriti nell’unità centrale in diverse posizioni reciproche, così riassumibili: 123, 132, 213, 231 , 312, 321. Erano quindi ammesse 6 diverse posizioni reciproche dei rotori (permutazioni). Pannello-a-prese-multiple: i possibili abbinamenti di 12 (6 x 2) sono moltissimi, per l’esattezza 100.391.791.500. Il numero totale di chiavi si ottiene moltiplicando le suddette possibilità: 17.576 x 6 x 100.391.791.500 = 10.586.916.764.424.000 in lettere circa 10 milioni di miliardi. Una volta presi accordi sui collegamenti del pannello, sull’anello, sull’ordine dei rotori e sul loro orientamento (cioè sui fattori che specificano la chiave), mittente e destinatario potevano crittare e decrittare i messaggi con facilità. D’altra parte l’intercettatore nemico, se fosse ricorso ad una strategia a prova di errore, avrebbe dovuto controllare 10 milioni di miliardi di combinazioni dei fattori di chiave. Un crittoanalista così rapido da controllare una combinazione al minuto, e così instancabile da lavorare giorno e notte sena interruzione, avrebbe impiegato un tempo superiore all’età dell’universo. (In effetti, questa valutazione eccede di ottimismo, perché nei calcoli precedenti non si è tenuto conto dell’anello. Se lo si fosse fatto, si sarebbe constatato che le combinazioni possibili erano molto più numerose. L’esercito tedesco decise dunque di adottare Enigma come cifratrice ufficiale delle proprie comunicazioni, in quanto considerato generatore di codici cifrati inviolabili. All’alba della Seconda Guerra Mondiale però decisero di incrementare ulteriormente il livello di sicurezza del dispositivo introducendo nuove caratteristiche: 1. Il numero di rotori possibili passò da 3 a 5. Pertanto ogni operatore Enigma aveva a disposizione 5 rotori tra i quali sceglierne 3 da dispor- 3 Enigma: versione informatica della macchina. 11 re in tutti modi possibili. Le combinazioni possibili dell’unità cifratrice passavano dunque da 6 a 60. 2. Il numero di cavetti a disposizione dell’operatore passarono da 6 a 10 determinando la possibilità di scambiare fino a 20 lettere nel pannello a prese multiple incrementando enormemente il numero di combinazioni possibili. Il numero di assetti possibili passava dunque da 10 milioni a circa 159 miliardi di miliardi, convincendo la maggior parte dei militari al fatto che Enigma fosse inviolabile. 3 Enigma: versione informatica della macchina. La realizzazione di Enigma informatica ha richiesto la considerazione di tutti gli aspetti descritti nella parte precedente. Il funzionamento di Enigma deve ovviamente essere virtualizzato con gli strumenti messi a disposizione dai linguaggi di alto livello più diffusi, oltre che ha dover prevedere il maggior grado di ottimizzazione possibile del codice. 3.1 Scelte strategiche di realizzazione. Per la realizzazione del programma di simulazione si è deciso di adottare il linguaggio ad oggetti Java Standard Edition. Le motivazioni di tale scelta sono state molteplici: • Il paradigma ad oggetti consente di realizzare delle strutture dati astratte dotate di particolari funzioni, applicabili separatamente a ciascuno di essi. Ciò ha permesso di ottenere una perfetta trasposizione dei componenti della macchina in ambiente virtuale. Sono infatti stati realizzati tanti oggetti quanti sono i componenti analizzati nella parte precedente e pertanto: – Scambiatore; – Riflessore; – Pannello a prese multiple; – Enigma (l’oggetto che rappresenta la cifratrice nel complesso e che istanzia ciascuno dei componenti necessari). • Essendo il Java un linguaggio interpretato multipiattaforma si è ritenuto, data l’attuale diffusione di OS diversi e l’evidente mancanza di un ambiente predominante come era stato Windows in passato, che l’uso di tale linguaggio fosse la scelta ideale. Non trattandosi poi di un programma necessitante ingenti capacità di calcolo, l’interpretazione anziché la compilazione non compromette in maniera eccessiva l’esperienza dell’utente. • L’ambiente di lavoro integrato (IDE) utilizzato per realizzare i vari componenti del programma, ovvero NetBeans 6.5, ha consentito un efficace organizzazione del progetto, considerate sia le peculiarità dell’editor (autocompletamento, ricerca ed organizzazione gerarchica dei file e degli oggeti creati) sia la comprensione nel pacchetto di strumenti per la creazione di GUI orientate agli eventi. 3 Enigma: versione informatica della macchina. 3.2 Specifiche di oggetti e metodi 3.2.1 Interfaccia Rotore 12 L’interfaccia Rotore rappresenta il punto di partenza per la creazione di oggetti capaci di eseguire la codifica secondo il modo di funzionamento di Enigma. I due metodi pubblici previsti, ossia forwardEncoding e backwardEncoding, dovranno essere implementati dalle sottoclassi di Rotore in maniera da consentire l’esecuzione della cifratura in avanti (ovvero dalla tastiera verso il riflessore) ed indietro (ovvero dal riflessore verso il visore). 3.2.2 Classe Scambiatore La classe Scabiatore implementa due interfacce: Rotore e ClickListener. L’implementazione di Rotore consente la realizzazione della cifratura in avanti ed indietro con i metodi ereditati dall’interfaccia Rotore mentre l’implementazione di ClickListener prevede l’implementazione del metodo clickArrived ovvero un metodo che consente la gestione di eventi di tipo ClickEvent (che verranno descritti in seguito). Il cuore del funzionamento dell’oggetto Scambiatore risiede nei due array di interi previsti nel codice ovvero forwardArray e backwardArray oltre che negli interi initialOffset e actualOffset. Il loro utilizzo è il seguente: • forwardArray: rappresenta come una lettera viene crittata se transitante dalla tastiera verso il riflessore. Immaginando di associare alla lettera a il valore 0, alla b il valore 1 e via dicendo è possibile realizzare la cifratura prelevando il valore memorizzato in forwardArray nella posizione ottenuta applicando la conversione precedentemente descritta. L’array dovrà contenere a sua volta valori compresi tra 0 e 25 esattamente quante sono le lettere dell’alfabeto considerato, per consentire la realizzazione di una corrispondenza biunivoca tra indice dell’array e contenuto. Se, ad esempio, i primi elementi dell’array fossero {24, 5, 6, ...} ne conseguirebbe che la a, applicando la conversione indicata in precedenza, sarà trasmutata nella lettera corrispondente al numero memorizzato alla posizione 0 dell’array, nel caso in esempio 24, e quindi nella lettera y. • backwardArray: rappresenta come una lettera viene crittata se transitante dal riflessore verso l’array. La conversione fra numeri e lettere è la stessa descritta in precedenza. Tuttavia l’array in esame deve essere costruito in maniera accorta. Essendo, nella più generale delle ipotesi, forwardArray un vettore di interi contenente valori compresi tra 0 e 25 che non seguono alcuna logica, backwardArray dovrà essere costruito nella seguente maniera: ad ogni indice del vettore deve essere associato un numero che rappresenta la posizione che ha l’indice considerato in forwardArray. Se, ad esempio, un forwardArray contenesse i valori {13, 5, ..., 0, 1}, backwardArray dovrà avere in posizione 0 il numero 24 perché il numero 0 occupa, in forwardArray la posizione numero 24 e, per la stessa ragione, dovrà avere in posizione 1 il numero 25. • initialOffset: rappresenta la configurazione iniziale dello scambiatore considerato. 3 Enigma: versione informatica della macchina. 13 • actualOffset: rappresenta il numero di “scatti” o di cifrature eseguite dal momento in cui l’oggetto viene istanziato. • l: rappresenta la lista degli oggetti ascoltatori agli eventi generati dallo scambiatore corrente. La modalità con cui i singoli caratteri vengono cifrati e decifrati, contenuti nei metodi pubblici ereditati forwardEncoding e backwardEncoding, sfruttano proprio la combinazione tra la rappresentazione dati utilizzata per realizzare i due array e gli indici specificati in precedenza. Se infatti si osserva la riga di codice necessaria per la cifratura in avanti r e t u r n { . . . } t h i s . forwardArray [ ( c + t h i s . i n i t i a l O f f s e t + this . actualOffset ) % this . size ] { . . . } ; e quella all’indietro r e t u r n { . . . } ( t h i s . backwardArray [ c ]− t h i s . a c t u a l O f f s e t − t h i s . i n i t i a l O f f s e t +2∗ t h i s . s i z e )%t h i s . s i z e { . . . } ; è evidente che non è possibile ottenere un risultato migliore (computazionalmente parlando). Un alternativa al gioco di indici e valori usati nei codici precedenti sarebbe stata rappresentata dalla realizzazione dell’avanzamento o posizionamento dello scambiatore, facendo avanzare fisicamente i valori memorizzati in ciascuno degli array in gioco. Se ad esempio si avesse avuto forwardArray caricato con {24, 5, 6, ..., 0, 1} per far avanzare di uno “scatto” lo scambiatore (e quindi simulare lo scatto che subivano gli scambiatori di Enigma ad ogni cifratura), sarebbe stato necessario ricostruire l’array come {5, 6, ..., 0, 1, 24}, un lavoro decisamente troppo gravoso per essere effettuato ad ogni chiamata del metodo di avanzamento. A seguito la specificazione della funzione dei metodi rimanenti: • Costruttori: accettano come parametri vettori di char, vettori di int o stringhe per realizzare forwardArray dopo aver verificato che i valori inseriti rispettino i vincoli dettati dalla rappresentazione dati adottata. Ciascuno costruttore prevede la chiamata del metodo privato makeBackward che non fa altro che popolare backwardArray secondo i valori immagazzinati in forwardArray (si tratta di un’operazione che deve essere effettuata solo una volta in quanto l’uso degli indici specificato in precedenza consente di evitare di dover ripopolare backwardArray ad ogni cifratura). • forwardEncoding e backwardEncoding: eseguono la cifratura verso il riflessore e verso il visore secondo lo schema di conversione accennato in precedenza (infatti sono passati come argomento interi e non caratteri). • goNext: incrementa actualOffset della quantità how, specificata come argomento. Si noterà che il metodo goNext esegue automaticamente le operazioni di verifica del termine del giro dello scambiatori: se la somma di initialOffset e actualOffset supera 26 (è come se un rotore di un contachilometri stesse passando dalla posizione 9 alla posizione 0) allora si generano gli eventi per lista di ascoltatori al fine di comunicare l’avvenuto termine del giro. La motivazione per l’uso di una gestione dei giri con eventi verrà chiarita nelle parti successiva. 3 Enigma: versione informatica della macchina. 14 • clickArrived: necessari per l’implementazione della classe ClickListener, eseguono come operazione l’avanzamento dello Scambiatore virtuale chiamante di una quantità specificata dall’evento passato come argomento, mediante la chiamata al metodo goNext specificato pocanzi. • ClickListnerList (classe privata): struttura dati a lista in cui verranno inseriti tutti gli ascoltatori di eventi generati dalla variabile oggetto che istanzia la classe in esame. I metodi rimanenti non richiedono particolari spiegazioni in quanto semplicemente modificanti dati appartenenti all’oggetto chiamante, in alcuni casi dopo aver effettuato un semplice controllo sull’input, o in alternativa restituenti i valori dei dati privati dell’oggetto. 3.2.3 Classe Riflessore La classe Riflessore implementa l’interfaccia Rotore. Come dovrebbe risultare chiaro dalla spiegazione del funzionamento di Enigma specificata nella parte 2, il riflessore risulta a tutti gli effetti un Rotore in quanto effettua la codifica dei valori numerici inseriti secondo lo schema di conversione specificato in precedenza. I metodi ereditati (forwardEncoding e backwardEncoding) sono necessari a mantenere la compatibilità con l’interfaccia Rotore sebbene, in effetti, eseguano le stesse operazioni. Potrebbe dunque risultare non chiaro il legame di ereditarietà tra Riflessore e Rotore ma la motivazione di questa scelta deriva da considerazioni strategiche precise. In effetti la generalizzazione degli oggetti mediante il meccanismo dell’ereditarietà, consente di poter costruire macchine virtuali Enigma aventi un grado di complessità decisamente maggiore del dispositivo inventato da Scherbius. Nulla impedirebbe ad un programmatore di realizzare una versione di Enigma dotata di un numero ragguardevole di Scambiatori e diversi meccanismi di riflessione, mediante gli oggetti che sono specificati attraverso il progetto che si sta descrivendo. La gestione di Riflessore diventa quindi maggiormente malleabile se considerato come una sottoclasse di Rotore ed è proprio questo il motivo dell’apparente forzatura realizzata. Il costruttore non prevede argomenti in quanto il riflessore viene realizzato direttamente dal programma. Dato infatti che esso non aumenta la complessità della cifratura ed avendo un ruolo pressoché passivo durante la codifica, si è ritenuto sufficiente mantenere uno schema riflessivo adeguato, che quindi realizzi la corrispondenza biunivoca tra 2 contenuti dell’array di elaborazione e i corrispettivi indici, per consentire una più semplice gestione dei dati da parte dell’utente e del programmatore. 3.2.4 Classe ClickEvent ed interfaccia ClickListener. La classe ClickEvent e l’interfaccia ClickListener sono necessari per la realizzazione degli “scatti” realizzati dalla macchina Enigma nel momento in cui un rotore ultima il proprio giro rendendo necessario l’avanzamento del Rotore successivo. In pratica la generazione di un evento di tipo ClickEvent, come si può notare dalla specificazione del clickArrived nella classe Scambiatore, simula appunto un 3 Enigma: versione informatica della macchina. 15 “click” ovvero uno scatto dello scambiatore corrente mediante l’applicazione del metodo goNext. La gestione di tale avvenimento mediante eventi consente di ottenere dei vantaggi importanti: • Innanzittutto automatizza il processo di verifica dell’avvenuto giro completo dello Scambiatore, in quanto i metodi coinvolti, ed in particolare goNext, prevedono la verifica costante di che punto dell’avanzamento si sia raggiunto. • Secondariamente c’è anche da dire che nonostante (come risulterà chiaro con la specificazione della classe Enigma) in questo progetto si sia deciso di adottare una strategia di avanzamento semplice (uguale al contachilometri) nulla vieta che altri programmatori, aventi altri fini diversi dalla simulazione puntuale di Enigma come si intende fare in questo progetto, decidano di adottare una modalità di avanzamento significativamente differente. Se ad esempio si volesse che ad ogni lettera cifrata il primo scambiatore avanzasse di 1 e il terzo di 2, allora la gestione ad eventi consente di facilitare tale compito perché la chiamata dei metodi previsti dalla classe interna di Scambiatore (ossia ClickListenerList) effettua in automatico tutte le operazioni necessarie. L’unica condizione per applicare tali regole è aggiungere in maniera oculata alla lista degli ascoltatori degli eventi di un singolo Scambiatore, gli ascoltatori corretti per attuare la strategia di avanzamento desiderata. 3.2.5 Classe PannelloPrese La classe PannelloPrese è la trasposizione virtuale del pannello a prese multiple di Enigma descritto nella sezione 2. Esso utilizza, allo stesso modo degli oggetti di tipo Scambiatore, un array di andata ed uno di ritorno per la cifratura dei caratteri ovviamente per le stesse ragioni specificate nelle sezioni precedenti. Si potrà notare tuttavia che i costruttori di PannelloPrese, sono decisamente più articolati dei costruttori della classe Scambiatore che si limitavano a controllare la correttezza degli input inseriti. La motivazione di tale complicazione risiede nel fatto che l’inserimento di una sequenza che rispetti le regole specificate per gli scambiatori non è più sufficiente per assicurare il corretto funzionamento del pannello. I controlli effettuati sono necessari infatti per verificare che nel momento in cui si specifica una lettera (o un numero) in una determinata posizione nel vettore, allora all’indice del vettore passato come argomento relativo alla posizione di tale lettera ci sia esattamente il valore relativo all’indice di tale lettera. Per chiarire con un esempio si potrebbe dire che se nella posizione 0 del vettore è inserito il valore 3 (e quindi la lettera D), allora in posizione 3 dello stesso vettore deve essere collocato il valore 0 (ovvero la A è trasformata in D e la D è trasformata in A). Tale controllo è necessario proprio perché, in caso tale corrispondenza non sia verificata, allora il pannello virtualizzato non avrebbe più il funzionamento del pannello a prese multiple di Enigma, ma quello di una sostituzione monoalfabetica, già menzionata in precedenza in questa documentazione. I metodi hanno le seguenti specificazioni: 3 Enigma: versione informatica della macchina. 16 • makeBackward: esattamente come il metodo omonimo della classe Scambiatore, realizza l’array di ritorno backwardArray, una volta che è stato correttamente inserito quello di andata forwardArray. • forwardEncoding e backwardEncoding: realizzano la cifratura in avanti e quella all’indietro passato un intero come argomento, allo stesso modo dei metodi omonimi della classe Scambiatore. I metodi rimanenti non necessitano di specificazioni ulteriori in quanto non realizzanti operazioni da dover chiarire. 3.2.6 Classe Enigma Si tratta della classe che esegue le operazioni di Enigma necessarie alla codifica dei messaggi. In particolare si è deciso che, escludendo le operazioni di configurazione, che prevedono diversi metodi detinati a tali funzioni, l’unico ruolo attivo degli oggetti della classe sarà attribuito ai metodi encodeChar e decodeChar. Pertanto si tratta di un sistema di codifica char-by-char. La classe Enigma si basa in particolare su 4 oggetti, che riproducono fedelmente i componenti utilizzati dalla versione reale della cifratrice: un pannello a prese multiple istanziato come oggetto di tipo PannelloPrese con il nome panel, un set di scambiatori possibili instanziato mediante un array di oggetti di tipo Scambiatore con il nome di possible, un set di scambiatori effettivamente usati nella codifica istanziato mediante un array di oggetti di tipo Scambiatore con il nome di used, un riflessore istanziato come un oggetto di tipo Riflessore con il nome di rif. L’unico costruttore previsto, privo di argomenti, realizza il caricamento di Enigma e l’istanziazione dell’array di Scambiatori possible. Tale caricamento avviene mediante la lettura di un file contenuto nella posizione “/files/scambiatori.conf”. Tale file dovrà contenere: nella prima riga il numero di scambiatori che si intendono specificare in seguito e nelle righe successive le stringhe contenenti lo schema di codifica degli scambiatori separate da una a-capo. In tale maniera non si preclude la possibilità di estensione del progetto stesso: aumentando il numero di righe e quindi di scambiatori è possibile aumentare il numero di combinazioni possibili degli scambiatori incrementando il grado di complessità del simulatore realizzato. A seguito la specificazione dei metodi realizzati: • setPanel: due metodi di cui si eseguito l’overloading (uno accetta un oggetto di tipo String come argomento e l’altro un array di char) consentono di istanziare la variabile panel richiamando il costruttore della classe PannelloPrese e passando come argomento la stringa o l’array argomento del metodo in analisi. • setTurningRules: metodo che fa si che il comportamento degli scambiatori di Enigma sia quello a contachilometri. Infatti aggiungendo alla lista degli ascoltatori di ogni scambiatore lo scambiatore successivo, è sufficiente far avanzare il primo per ottenere il comportamento sperato: applicando infatti a tale scambiatore il metodo goNext, ogni volta che si esegue un giro completo di ciascuno scambiatore questo genererà un evento di tipo ClickEvent lanciato a tutti gli ascoltatori presenti nella propria lista di ascoltatori, realizzando in maniera efficace il contachilometri desiderato. 3 Enigma: versione informatica della macchina. 17 • setUsed: istanzia la variabile used secondo l’ordine specificato dall’array di interi passato come argomento. Si ritenuto di dover copiare gli Scambiatori nel vettore used da possible e non solo far riferimento (come è noto le variabili oggetto sono puntatori ad oggetto nel linguaggio Java), per evitare che ci fossero problemi di concorrenza dovuti al passaggio di un vettore valido ma inconsistente da un punto di vista logico (il vettore {0,0,0} è perfettamente valido in quanto tali elementi esistono nel vettore possible). È tuttavia consigliabile evitare che si verifichino casi di ripetizione nel momento in cui si passa l’array di interi perché ciò implica una riproduzione non fedele della cifratrice. • setOffset: dopo aver effettuato i dovuti controlli, in corrispondena degli indici dell’array passato come argomento, imposta il valore della varibile initOffset degli scambiatori utilizzati. • encodeChar: accetta un carattere alfabetico minuscolo, fa avanzare di una posizione il primo scambiatore e restituisce il carattere maiuscolo relativo alla lettera passata come argomento. Restituisce quindi il valore trasmutato del carattere di partenza passando quindi da testo chiaro a testo cifrato (si è deciso di utilizzare la convenzione crittografica secondo la quale il testo chiaro è minuscolo e quello cifrato maiuscolo). L’utility di cifratura si compone, come si può notare delle seguenti fasi: la trasformazione del carattere passato come argomento secondo le regole dell’oggetto panel; un ciclo for in cui, ad ogni passo, ciascuno scambiatore utilizzato modifica il risultato parziale della codifica dal primo verso l’ultimo; la trasformazione del carattere secondo le regole del riflessore; un ciclo for in cui viene realizzata la cifratura da ciascuno scambiatore utilizzato modificando il risultato parziale fin qui ottenuto applicando il metodo backwardEncoding (dall’ultimo verso il primo); un ultimo passaggio attraverso il pannello a prese multiple per la trasformazione finale. Al termine della cifratura viene richiamato il metodo goNext per l’avanzamento del primo scambiatore ed infine restituito il risultato. • decodeChar: richiama il metodo encodeChar dopo aver modificato il testo da decodificare in minuscolo in maniera che esso possa essere elaborato. Tale facilità di utilizzo è dovuta, come dovrebbe essere noto, al riflessore e pertanto il metodo in analisi si limita a modificare leggermente i dati passati affinché essi vengano elaborati. Si noti che sia il metodo encodeChar che il metodo decodeChar elaborano solo caratteri alfabetici, ogni altro carattere introdotto non viene mai elaborato e non comporta effetto alcuno sulla cifratrice. I metodi non descritti, come già avvenuto in questa documentazione, eseguono delle operazioni tanto elementari da non meritare delucidazione alcuna. 3.2.7 Classe EnigmaSimulator La classe EnigmaSimulator contiene le istruzioni per la realizzazione della GUI simulante Enigma. Buona parte del codice è stata autogenerata da NetBeans 6.5 ma i metodi che non hanno nulla a che fare con l’estetica, e pertanto che specificano il comportamento dei singoli componenti inseriti e la gestione della cifratura/decifratura, sono stati realizzati dal programmatore. 3 Enigma: versione informatica della macchina. 18 Gli oggetti grafici principali sono: • 3 Caselle Combinate: contengono gli scambiatori da utilizzare durante la cifratura nell’ordine delle caselle stesse. • 3 Spinner (istanziati da sorgente): contengono la disposizione attuale degli scambiatori di Enigma (l’unità cifratrice). • 1 Tabella: rappresenta il pannello a prese multiple. Nella prima colonna le lettere di partenza, nella seconda quelle di arrivo. • 1 Pulsante di conferma: richiama il metodo per verificare che le lettere inserite nella seconda colonna della tabella del pannello rappresentino una sequenza valida per il pannello a prese multiple e, in caso affermativo, modifica con le disposizioni inserite il pannello a prese multiple di Enigma. • 2 Aree di Testo: uno contiene il testo di partenza (cifrato o da decifrare) e l’altro contiene il testo di arrivo (decifrato o da cifrare). • 1 Gruppo di Radio-button: specificano se si intende cifrare o decifrare. Questa specificazione è necessaria in quanto, come già ricordato in precedenza, esiste una convenzione precisa per i testi cifrati e una atrettanto precisa per i testi chiari. • 3 Pulsanti: per le operazioni di cifratura: – Normalizza: richiama il metodo che elimina tutti i caratteri che non verranno elaborati da enigma o modifica i caratteri che devono esserlo per essere elaborati (ad esempio le lettere accentate vengono convertite in lettere non accentate). – Avvia processo: richiama il metodo che esegue l’operazione specificata nel radio-button confermato. – Inverti caselle: richiama il metodo che copia il contenuto della casella di arrivo in quella di partenza per facilitare le operazioni di codificadecodifica in una sola macchina. A seguito la specificazione dei metodi necessari alla gestione di eventi e del funzionamento della cifratrice virtuale: • SimpleTableModeListner (classe privata): classe necessaria alla gestione delle modifiche della tabella che rappresenta il pannello a prese multiple. Il codice con i controlli specificati esegue, in sostanza, le seguenti operazioni: – Controlla che la prima colonna, che rappresenta la lettera di partenza del pannello a prese multiple, non venga mai modificata. – Controlla cha la seconda colonna, che rappresenta la lettera di arrivo del pannello a prese multiple, vengano inseriti caratteri validi. • prepare: istanzia tutte le varibili necessarie alla gestione della cifratura e modifica i valori degli oggetti grafici specificati. • setSpinnerChar: modifica i valori degli spinner a seconda del valore attuale dell’offset di ciascuno scambiatore di Enigma. 4 La “Bomba” di Turing 19 • setCombos: carica il contenuto delle caselle combinate a seconda del numero di scambiatori presenti nell’oggetto Enigma istanziato e verifica che non si verifichino ripetizioni tra i valori specificati. Gli altri metodi presenti vengono richiamati nel momento in cui viene generato l’evento relativo agli oggetti grafici specificati in precedenza. Pertanto la funzione di tali metodi è stata già descritta con la specificazione dei comportamenti degli stessi oggetti grafici. 4 La “Bomba” di Turing 4.1 Sinossi del primo tentativo di crittoanalisi: la “bomba” di Rejewski Nel momento in cui Enigma venne adottata dall’esercito tedesco come cifratrice ufficiale delle comunicazioni della Germania, quasi tutti i paesi d’Europa avevano rinunciato ad ogni tentativo di breccia nel crittosistema dei militari tedeschi. Enigma era ritenuta praticamente impenetrabile e non vi era nessuna tecnica sviluppata in precedenza che potesse aiutare nella crittoanalisi dei codici prodotti dalla macchina. Ciononostante il primo tentativo di attacco ad Enigma si tenne a partire dal 1931 al Biuro Szyfròw, l’ufficio di codici e cifre della Polonia. Qui un giovane statistico di nome Marian Rejewski, assoldato dopo che gli alti membri dell’esercito si erano resi conto che per affrontare Enigma fosse necessaria una preparazione tecnico-scientifica e non solo linguistica, trovò il primo enorme punto debole di Enigma il quale gli consentì in appena un anno di trovare il modo di individuare l’assetto dell’unità scambiatrice in poche ore. Come è ben noto la chiave necessaria per impostare correttamente Enigma era costituita da 3 informazioni: la disposizione degli scambiatori negli alloggiamenti, la posizione degli scambiatori e le lettere da sostituire nel pannello a prese multiple. Anche se il grado di sicurezza garantito dal gran numero di chiavi disponibili era decisamente alto, i tedeschi per aumentare ulteriormente l’affidabilità del proprio sistema di codifica decisero di introdurre una nuova variabile: la chiave di messaggio. La chiave di messaggio corrispondeva in pratica alla posizione degli scambiatori usata per cifrare il contenuto dell’intero messaggio. L’assetto inserito nel cifrario era utilizzato solo ed esclusivamente per cifrare la chiave di messaggio che veniva inviata 2 volte per evitare errori durante la trasmissione. Un esempio di modus operandi poteva essere dunque il seguente. • L’operatore di Enigma X configurava la propria macchina inserendo i dati descritti nel proprio cifrario, ipotizziamo con un posizionamento degli scambiatori di GTQ. Questo dato verrà d’ora in avanti chiamato chiave giornaliera o quotidiana. • X sceglieva la chiave che avrebbe usato per il proprio messaggio, poniamo UJL. Questo dato è la chiave di messaggio. • Con la propria Enigma configurata secondo la chiave quotidiana, X cifrava la stringa UJLUJL, ottenendo, per esempio KIVBLE. 4 La “Bomba” di Turing 20 • X riconfigurava Enigma inserendo come assetto degli scambiatori UJL anziché GTQ e cifrava il messaggio. • L’insieme di KIVBLE ed il messaggio cifrato veniva infine consegnato al marconista, il quale lo inviava all’operatore Enigma Y mediante codice morse. L’operatore Enigma Y che avesse voluto leggere il messaggio inviato da X eseguiva quindi le seguenti operazioni: • Y, con la propria macchina configurata secondo le indicazioni del cifrario, riceveva il messaggio dal marconista. • Prelevava le prime sei lettere, nel nostro esempio KIVBLE, e le decifrava con la propria macchina configurata con la chiave giornaliera GTQ ottenendo la stringa UJLUJL. • Saputo che la chiave di messaggio per quel particolare testo sarebbe stata UJL, Y riposizionava gli scambiatori Enigma secondo l’ordine UJL e decifrava il resto del messaggio ricevuto. Il vantaggio di questo sistema di invio delle informazioni è evidente: la parte di messaggio più a rischio perché cifrata secondo le informazioni del cifrario era talmente ridotta che ogni tipo di strategia di analisi sarebbe stata inutile. Come è noto, per eseguire anche solo l’analisi delle frequenze è necessario disporre di un testo ragguardevole per riuscire ad ottenere dei risultati verosimili. Tuttavia avendo scelto di cifrare per due volte di seguito lo stesso messaggio, i tedeschi avevano dato la possibilità al crittoanalista polacco Rejewski di far breccia nei codici generati da Enigma. Il suo metodo crittoanalitico si pasava essenzialmente su di un unica considerazione: esisteva un legame molto forte tra la prima e la quarta lettera di ogni messaggio, così come tra la seconda e la quinta, così come tra la terza e la sesta, in quanto lettere uguali, e questo legame era determinato dalla chiave quotidiana contenuta nel cifrario di Enigma. Questa considerazione si rivelò praticolarmente proficua per Rejewski perché si accorse ben presto che il legame esistente tra queste coppie di lettere era caratteristico della chiave quotidiana usata per quel particolare giorno e soprattutto era indipendente dal pannello a prese multiple. Eliminato il pannello era dunque sufficiente verificare le caratteristiche dei legami esistenti tra le coppie di lettere per individuare in poco tempo la chiave giornaliera per gli assetti degli scambiatori, operazione che era effettuata meccanicamente tramite l’uso di un dispositivo elettromeccanico chiamato “bomba”. La “bomba” rappresentava l’evoluzione delle tecniche crittoanalitiche in quanto, esattamente come Enigma aveva rivoluzionato la crittografia introducendo procedure elettromeccaniche per la produzione di messaggi segreti, la bomba aveva introdotto elementi elettromeccanici per far breccia nei codici nemici. Grazie agli sforzi di Rejewski i polacchi furono in grado di decifrare praticamente tutte le comunicazioni segrete dei tedeschi dal 1931 fino all’alba dello scoppio della seconda guerra mondiale nel 1938, anno in cui i tedeschi aggiornarono il proprio crittosistema secondo le indicazioni specificate in precedenza nella presente documentazione (5 scambiatori da cui sceglierne 3 + 20 lettere da 4 La “Bomba” di Turing 21 poter sostituire nel pannello a prese multiple) oltre che riducendo ad una singola copia l’invio della chiave di messaggio (nell’esempio sopra descritto, anzichè inviare UJLUJL l’operatore avrebbe inviato solo UJL). 4.2 Bletchley park Dopo il successo dei crittoanalisti polacchi il mito dell’inviolabilità di Enigma era stato sfatato definitivamente. I successi del Biuro Szyfròw si erano interrotti a causa dei nuovi scambiatori e dei nuovi cavetti per il pannello a prese multiple; tuttavia, restava il fatto che Enigma non poteva essere più considerata inattaccabile. L’esempio dei polacchi fece inoltre capire agli alleati l’importanza di reclutare crittoanalisti anche tra i matematici. In Gran Bretagna, la Stanza 40, ovvero l’ufficio di codici e cifre di Sua Maestà, era sempre stata appannaggio di linguisti ed umanisti, ma da quel momento ci fu una sforzo concentrato per riequilibrare la sua composizione, accogliendo matematici e scienziati. Il reclutamento avvenne in larga misura tramite amicizie: erano i membri dello staff che si mettevano in contatto coi vecchi compagni di corso di Oxford e Cambridge, e ne sondavano l’interesse per la crittografia professionale. C’era anche una rete che reclutava donne con i diplomi di college prestigiosi, come il Newnham College e il Girton College di Cambridge. Le nuove reclute non venivano chiamate nella Stanza 40 di Londra, ma a Bletchley Park, nel Buckinghamshire, sede della Government Code and Cypher School (GC&CS), una nuova organizzazione cui la vecchia Stanza 40 passava le consegne. Bletchley Park poteva ospitare un personale molto più numeroso, fatto importante perché ci si aspettava che il conflitto avrebbe prodotto una valanga di intercettazioni crittate. Durante la prima guerra mondiale la Germania aveva trasmesso due milioni di parole al mese, ma si prevedeva che i progressi tecnologici nel campo delle radiotrasmissioni avrebbero fatto raggiungere i due milioni di parole al giorno. Nell’autunno 1939, scienziati e matematici presero confidenza col complesso funzionamento di Enigma, e in tempo relativamente breve riuscirono a padroneggiare il metodo di analisi elaborato dai polacchi. Le risorse e il personale dell’organizzazione inglese erano superiori a quelli del Biuro Szyfròw, perciò essa fu in grado di superare il problema dela maggior numero di scambiatori, e in generale, della maggiore resistenza della nuova versione di Enigma. Ogni ventiquattr’ore gli operatori tedeschi passavano simultaneamente ad una nuova chiave giornaliera, e i crittoanalisti britannici ingaggiavano una lotta contro il tempo. Se riuscivano a scoprire l’assetto base di Enigma, potevano decifrare tutte le comunicazioni radio tedesche fino all’entrata in servizio della nuova chiave, raccogliendo dati di enorme importanza militare. Assimilata la strategia dei polacchi, i crittoanalisti di Bletchley cominciarono a trovare nuove scorciatoie per scoprire le chiavi di Enigma. Per esempio, approfittarono del fatto che gli operatori tedeschi a volte sceglievano chiavi ovvie. In teoria, essi avrebbero dovuto formare la chiave di messaggio con tre lettere rigorosamente casuali. Di fatto, anche per lo stress della situazione bellica, invece di spremere le meningi e creare una sequenza casuale molti operatori premevano tre lettere consecutive sulla tastiera, generando stringhe come QWE o BNM. Queste banali, prevedibili chiavi di messaggio, vennero soprannominate cillies. Un’altro tipo di cilly implicava l’uso ripetuto della stessa chiave di messaggio - 4 La “Bomba” di Turing 22 magari le iniziali della fidanzata dell’operatore; sembra che da una circostanza del genere, connessa con la chiave CIL, sia derivato il soprannome che designò l’intera categoria. Prima di lanciare contro Enigma un attacco in grande stile, diventò abitudine dei crittoanalisti inglesi provare cillies, e a volte il trucco, con l’aggiunta di un po’ di intuito, pagava. I cillies non erano punti deboli di Enigma, ma del modo in cui veniva usata. Anche errori umani commessi a un livello gerarchico più elevato compromisero la sicurezza del sistema. I responsabili della compilazione dei cifrari dovevano decidere quali scambiatori, e in quale posizione, sarebbero stati impiegati di giorno in giorno. Essi tentarono di assicurare l’imprevedibilità delle posizioni stabilendo che nessuno scambiatore potesse occuparne una per due giorni consecutivi. Così, indicando gli scambiatori con numero da 0 a 4, il primo giorno poteva essere prescritta la disposizione 0-2-3, il secondo la disposizione 1-0-4, ma non la 1-0-3, perché il terzo scambiatore sarebbe stato il medesimo e nella stessa posizione. A prima vista questa regola parrebbe sensata, perché genera disposizioni sempre diverse; ma introducendo un’importante limitazione ad ogni disposizione tranne la prima, facilita molto il lavoro dei crittoanalisti. Dal punto di vista matematico, in questo modo i compilatori dei cifrari ridussero di circa il cinquanta per cento il numero di possibili disposizioni degli scambiatori. I crittoanalisti di Bletchley compresero quello che stava accadendo, e ne approfittarono. Una volta individuata la disposizione di un giorno, era possibile ridurre di circa la metà le possibili disposizioni del giorno successivo. Naturalmente, anche il carico di lavoro in questo modo risultava dimezzato. Una regola analoga a quella degli scambiatori stabiliva che dall’assetto del pannello a prese multiple andassero esclusi i collegamenti con lettere contigue. Così, S si poteva scambiare con qualsiasi lettera tranne R e T. L’idea era che scambi così ovvi andassero evitati, ma ancora una volta ciò riduceva gravemente il numero di chiavi possibili. La ricerca di nuove scorciatoie era necessaria perché la macchina Enigma continuò ad evolvere per tutta la durata del conflitto. I crittoanalisti furono costretti a raffinare, modificare e perfino riprogettare le bombe derivate da Rejewski, e ad escogitare strategie originali. Una delle ragioni del loro successo fu lo strano miscuglio di matematici, scienziati, liguisti, cultori di studi classici, maestri di scacchi e appassionati di cruciverba che popolavano le «capanne», come venivano chiamati i locali in cui risiedevano i vari crittoanalisti e dove svolgevano il loro lavoro. Un problema ostico passava da un decrittatore all’altro finché cadeva sotto gli occhi di una persona con la mentalità adatta a risolverlo, o almeno a semplificarlo prima di passarlo ad un collega. Per Bletchley passarono molti grandi crittoanalisti, che fecero scoperte importanti; una descrizione particolareggiata di tutti i loro contributi richiederebbe diversi volumi. Tuttavia, se c’è uno studioso che merita un posto a parte, questi è Alan Turing, colui che è considerato il padre dell’informatica, che individuò il principale punto debole di Enigma e lo sfruttò fino in fondo. Grazie a Turing fu possibile continuare a tradurre messaggi Enigma anche nelle circostanze più difficili. 4.3 La “bomba” di Turing Il sistema crittoanalitico di Rejewski si basava sul fatto che gli operatori Enigma inviavano 2 volte la chiave di messaggio, crittata con la chiave giornaliera, prima di inviare il messaggio vero e proprio, crittato con la chiave di messaggio. 4 La “Bomba” di Turing 23 Una volta individuata la chiave giornaliera grazie ai collegamenti tra le coppie di lettere e l’ausilio di tutte le “bombe” capaci di verificare tutte le possibili disposizioni degli scambiatori, per i crittoanalisti la maggior parte del lavoro era fatto e il resto della giornata poteva essere trascorso decrittando tutti i messaggi intercettati. Tuttavia se fosse mancato il duplice invio della chiave, così come sarebbe accaduto nel giro di pochi anni, tutto il lavoro fatto dai polacchi sarebbe stato inutile. Ecco perché il lavoro di Alan Turing venne finalizzato all’individuazione di una falla sistemica, indipendente dal modo in cui Enigma venisse utilizzata dagli operatori e che coinvolgesse, al più, la conoscenza di parte del testo chiaro. Col passare del tempo, Turing constatò che a Bletchley si stava accumulando una patrimonio di messaggi decifrati, e notò che molti di essi rivelavano una struttura piuttosto rigida. Pensò quindi che il contenuto dei crittogrammi nuovi si potesse spesso inferire, almeno in parte, in base ai crittogrammi risolti, prestando attenzione a dati come la provenienza del messaggio e l’ora di trasmissione. Per esempio, l’esperienza insegnava che tutti i giorni, poco dopo le sei del mattino, i tedeschi trasmettevano brevi bollettini meteorologici cifrati. Perciò, un crittogramma captato alle 6.05 antimeridiane quasi certamente conteneva la parola Wetter («tempo atmosferico» in tedesco). Il rigido modus operandi delle organizzazioni militari implicava che simili comunicazioni fossero stereotipate anche nello stile. Questo aumentava la probabilità che il crittogramma contenesse parole come wetter in posizioni fisse. L’esperienza poteva quindi fornire indicazioni ancora più precise, per esempio che le prime sei lettere della seconda riga di certi tipi di crittogrammi corrispodevano quasi sempre alla parola wetter. Quando un frammento di testo chiaro poteva essere interpretato in base a considerazioni non crittoanalitiche, si parlava di crib («culla», o «copiatura», nel senso della ben nota scorrettezza scolastica). Turing era sicuro di poter approfittare dei cribs per creare una procedimento di soluzione dei crittogrammi Enigma diverso da quello di Rejewski. Disponendo del crittogramma e sapendo che una sua parte, per esempio ETJWPX, corrispondeva a wetter, la sfida sarebbe consistita nell’individuare l’assetto di Enigma che trasformava la seconda sequenza di lettere nella prima. Il metodo più diretto, ma poco pratico, in cui un crittoanalista poteva affrontare il problema era prendere una replica di Enigma, digitare wetter e vedere se il risultato era ETJWPX; se non lo era, cambiare a poco a poco, una per volta e con metodo, le regolazioni (cominciando dai cavetti, proseguendo con gli scambiatori, e così via) fino ad ottenere la sequenza cercata. Il guaio era ciò che in crittoanalisi rende spesso inutile il metodo per prova di errore o a forza bruta (brute force): gli assetti possibili erano 159 miliardi di miliardi, e la guerra sarebbe finita molto prima che il crittoanalista avesse effettuato un’insignificante porzione dei controlli necessari. Per semplificare il problema, Turing imitò la strategia di Rejewski di scomporre l’assetto di Enigma in parti che comportassero un numero più accettabile di possibilità. In particolare, voleva separare il problema della disposizione degli scambiatori (quali scambiatori usare, e in quali alloggiamenti) e del loro orientamento, dal problema dei collegamenti del pannello a prese multiple. Se per esempio avesse potuto ricavare da un crib un indizio che non avesse nulla a che fare col pannello, sarebbe forse riuscito a trovare il modo di controllare i 1.054.560 assetti (60 disposizioni x 17.576 orientamenti) degli scambiatori. Ri- 4 La “Bomba” di Turing 24 solto questo problema, quello del pannello a prese multiple si sarebbe potuto affrontare per via deduttiva. Alla fine, la sua attenzione si concentrò su un particolare crib, contenente delle concatenazioni. Tali concatenazioni riguardavano le lettere del testo chiaro e del testo crittato nell’ambito di un crib. Per esempio, il crib mostrato in figura 7 contiene una concatenazione: Fig. 7: Uno dei cribs di Turing, con la concatenazione messa in evidenza Non bisogna dimenticare che i crib sono solo ipotesi. Tuttavia, se questa particolare ipotesi è corretta, possiamo collegare le lettere w→E, e→T, t→W, in quanto appartenenti alla concatenazione. Anche se non sappiamo nulla degli assetti della macchina Enigma, possiamo chiamare «a» il primo assetto, qualunque esso sia. Di questo assetto sappiamo solo che porta a cifrare w come E. Dopo di che, il primo scambiatore avanza di una lettera, facendo assumere ad Enigma l’assetto «a+1», e la lettera e è cifrata come T. Il primo scambiatore avanza di un altro posto e cifra una lettera che non fa parte della concatenazione, ragion per cui ignoriamo questa cifratura. Avanza ancora di uno spazio, e di nuovo ci imbattiamo in una lettera inclusa nella concatenazione: sappiamo che nell’assetto «a+3», t è cifrata come W. Riassumendo, siamo sicuri che: Nell’assetto«a» Enigma critta w come E Nell’assetto«a+1» Enigma critta e come T Nell’assetto«a+3» Enigma critta t come W Per ora la concatenazione sembra solo una curiosità, ma Turing sviluppò tutte le implicazioni dei rapporti all’interno del crib, e capì che rappresentavano proprio il tipo di drastica scorciatoia che gli occorreva per far breccia in Enigma. Invece di lavorare con una sola macchina per verificare ogni assetto egli cominciò ad usarne tre: una per la cifratura di w come E, un’altra per la cifratura di e come T, la terza per la cifratura di t come W. Le tre macchine avevano assetti identici, se si eccettua il fatto che la seconda avrebbe avuto gli scambiatori orientati un posto avanti rispetto alla prima (a+1), e la terza avrebbe avuto gli scambiatori orientati di tre posti avanti rispetto alla prima (a+3). Stabilito ciò, Turing si immaginò un trafelato crittoanalista che senza sosta inseriva e disinseriva cavetti, mutava posto agli scambiatori e ne modificava l’orientamento, finché ogni macchina avesse cifrato come suggerito dal crib. Fin qui, Turing non sembra aver concluso molto. Il povero crittoanalista ha ancora 159 miliardi di miliardi di assetti da controllare, e per di più deve farlo non su una, ma su tre macchine Enigma contemporaneamente. Ma il 4 La “Bomba” di Turing 25 passo successivo del ragionamento di Turing trasforma la natura della sfida, e la semplifica radicalmente. Egli immaginò di collegare le tre cifratrici con cavi elettrici posti tra l’input di una macchina e l’output della successiva, come mostrato in figura 8. In effetti, la concatenazione ciclica del crib è riprodotta dal circuito elettrico. Il circuito si chiuderebbe, permettendo alla corrente di percorrerlo, solo quando tutte e tre le macchine avessero raggiunto un assetto che realizzasse la concatenazione. A questo punto, se una lampadina facesse parte del circuito essa si accenderebbe, segnalando che la ricerca ha avuto buon esito. Per ora, ogni macchina doveva ancora controllare 159 miliardi di miliardi di combinazioni - il procedimento era stato automatizzato, non semplificato. Ma i passi compiuti fin qui erano solo preparatori in vista del vero colpo da maestro, che d’un tratto avrebbe reso il controllo degli assetti cento milioni di milioni di volte più facile. Turing aveva costruito il circuito in modo da annullare l’effetto del pannello a prese multiple, e poter ignorare i miliardi di assetti possibili di questo elemento. Osservando la figura 8 si constata che nella prima macchina Enigma la corrente entra negli scambiatori ed emerge in corrispondenza di una lettera sconosciuta, che chiameremo L1 . Poi la corrente attraversa il pannello e trasforma L1 in E. Questa E è collegata tramite un filo elettrico alla e della seconda macchina Enigma, e al passaggio della corrente attraverso il scondo pannello si trasforma di nuovo in L1 . In altre parole, i due pannelli a prese multiple si annullano a vicenda. In modo analogo, la corrente in uscita dagli scambiatori della seconda macchina Enigma entra negli scambiatori in corrispondenza di L2 , prima di essere trasformata in T. Questa T è collegata tramite un filo elettrico alla t della terza Enigma, e col passaggio della corrente attraverso il terzo pannello si trasforma di nuovo in L2 . In breve, i pannelli si annullano a vicenda in tutto il circuito; perciò, si poteva prescindere completamente della loro esistenza. Turing aveva solo bisogno di collegare l’output del primo gruppo di scambiatori in corrispondenza di L1 , all’input del secondo gruppo di scambiatori, sempre in corrispondenza di L1 , e così via. Purtroppo egli non conosceva il valore di L1 , perciò era costretto a collegare le 26 uscite del primo gruppo di scambiatori ai 26 ingressi corrispondenti del secondo gruppo di scambiatori, e così via. In questo modo si formavano 26 circuiti, ciascuno dei quali dotato di una lampadina a segnalarne la chiusura. I tre gruppi di scambiatori potevano così limitarsi a controllare i 17.576 orientamenti loro concessi, col secondo gruppo di scambiatori sempre un passo avanti del primo, e il terzo due passi avanti il secondo. Alla fine, scoperto il giusto orientamento degli scambiatori, uno dei circuiti si chiudeva causando l’accensione di una lampadina. Se gli scambiatori avessero mutato orientamento ogni secondo, il controllo di tutti gli orientamenti avrebbe richiesto solo 5 ore. Restavano solo due difficoltà. Innanzitutto era possibile che le tre macchine funzionassero con una disposizione errata degli scambiatori. Poiché le cifratrici contenevano tre scambiatori su cinque, disposti in qualunque ordine, le disposizioni possibili erano sessanta. Quindi, controllati i 17.576 orientamenti, se la lampada non si fosse illuminata sarebbe stato necessario cambiare disposizione, e ripetere il procedimento. Un’alternativa era munirsi di un gran numero di repliche di Enigma (sessanta gruppi di tre) e farle lavorare in parallelo. La seconda difficoltà riguardava la determinazione del’assetto del pannello a prese multiple, una volta risolti i problemi degli scambiatori. In questo caso, 4 La “Bomba” di Turing 26 Fig. 8: La concatenazione del crib può essere riprodotta sotto forma di concatenazione elettrica. Tre macchine Enigma sono regolate in modo identico, se si eccettua il fatto che la seconda ha gli scambiatori orientati un poto avanti rispetto alla prima (a+1), e la terza ha gli scambiatori orientati di tre posti avanti rispetto alla prima (a+3). L’output di ciascuna Enigma è poi collegato all’input della successiva. Durante il funzionamento, i tre gruppi di scambiatori avanzano all’unisono finché il circuito si chiude e la lampadina si accende. L’assetto raggiunto in quel momento è quello cercato. Nel diagramma qui sopra il circuito è completo, cioè corrisponde al giusto assetto degli scambiatori. 4 La “Bomba” di Turing 27 la soluzione era relativamente semplice. Usando una macchina Enigma con la giusta disposizione e il giusto orientamento degli scambiatori, il crittoanalista avrebbe digitato il testo cifrato e osservato il testo chiaro risultante. Una stringa come tewwer avrebbe suggerito, per esempio, di collegare con un cavetto le prese t e w del pannello. L’immissione di altri frammenti di crittogramma avrebbe chiarito la posizione degli altri cavetti. L’uso simultaneo di cribs, concatenazioni e cifratrici collegate elettricamente portò a un risultato quasi miracoloso, che solo Turing, con la sua cultura matematica e la propensione a ragionare in termini di congegni immaginari, avrebbe potuto conseguire. La macchina astratta universale di Turing era stata da lui concepita per far luce su sottili questioni teoriche circa l’indecidibilità matematica; ma interessi puramente accademici l’avevano abituato ad uno stile di ragionamento assai propizio all’ideazione di un’altra macchina: un apparecchiatura per la decifrazione automatica capace di influenzare eventi tragicamente reali. Le idee di Turing si concretizzarono nel 1940, quando egli terminò il progetto di quella che sarebbe passata alla storia come la “bomba” di Turing, così chiamata per il ticchettio prodotto dagli scambiatori che avanzavano meccanicamente oltre che per fare onore all’ideatore dell’omonimo dispositivo creato da Rejewski. Fig. 9: La “bomba” di Turing. Ricostruzione al “Bletchley Park Museum” Il primo prototipo di bomba, battezzata «Victory», arrivò a Bletchley Park il 14 marzo 1940. Fu subito messa in funzione, ma i risultati iniziali non furono esattamente entusiasmanti. Il congegno, molto più lento di quanto ci si aspettasse, impiegò una settimana per individuare una sola chiave. Fu fatto uno sforzo collettivo per migliorare la sua efficienza, e un progetto modificato venne consegnato poche settimane più tardi. Ma per disporre della nuova versione di bomba ci vollero 4 mesi. Nel frattempo i crittoanalisti dovettero affrontare la calamità da loro temuta. Il 10 maggio 1940 i tedeschi cambiarono la procedura di comunicazione delle chiavi. La chiave di messaggio non venne più ripetuta e le decifrazioni di crittogrammi Enigma crollarono di colpo. Il blackout durò fino 5 La “Bomba” di Turing: versione Informatica 28 all’8 agosto, quando arrivò la nuova bomba. Chiamata «Agnus Dei», o «Agnes» per brevità, essa corrispondeva al dispositivo sognato da Turing. Di li a otto mesi le bombe in funzione furono quindici: divoravano cribs, controllavano assetti, rivelavano chiavi, ticchettavano come un esercito di nonne intente a sferruzzare. Se tutto andava bene, una bomba era in grado di individuare una chiave Enigma in una sessantina di minuti al massimo. Una volta stabiliti i collegamenti sul pannello e la disposizione degli scambiatori (cioè la chiave di messaggio) per una intercettazione, dedurre la chiave giornaliera diventava un compito facile. Allora si potevano decifrare tutti i messaggi spediti quello stesso giorno. Anche se le bombe rappresentavano un progresso crittoanalitico di prima grandezza, la decifrazione non era diventata una mera routine. C’erano molti ostacoli da superare prima che uno di quei congegni potesse cercare una chiave. Per esempio, per funzionare la bomba aveva bisogno di crib. I solutori di codici con più esperienza lo indicavano agli operatori, ma niente garantiva che il suggerimento fosse giusto. E anche se era giusto, poteva non riferirsi al punto giusto del crittogramma; in altre parole, la parola o la frase che secondo il crittoanalista si trovava nel messaggio in codice poteva davvero farne parte, ma in una posizione diversa da quella da lui ipotizzata. In questo caso, però, un semplice trucco permetteva di controllare se un crib si trovasse nella posizione corretta. Nel crib seguente, il crittoanalista è sicuro che il testo chiaro faccia parte del crittogramma, ma non è certo di dove collocarlo alle lettere giuste. Una delle caratteristiche di Enigma, dovuta alla presenza del riflessore, era l’impossibilità di cifrare una lettera con se stessa. Così, a può essere cifrata in qualunque modo fuorché come A. Ne consegue che il crib dell’esempio dev’essere male allineato: infatti la prima e di wetter coincide con una E del crittogramma. Per trovare l’allineamento giusto, conviene spostare il testo chiaro rispetto al crittogramma finché nessuna lettera è al di sopra di una lettera uguale. Muovendo il testo chiaro di un posto verso sinistra, l’allineamento non è ancora soddisfacente, questa volta perché la prima s di sechs è sopra un’altra S. Invece, muovendo il testo chiaro di un posto verso destra, non si osservano sovrapposizioni inammissibili. Questo crib andrebbe quindi utilizzato per effettuare la ricerca automatica della chiave giornaliera. 5 5.1 La “Bomba” di Turing: versione Informatica Considerazioni sulla simulazione La simulazione della “Bomba” di Turing necessita di alcune considerazioni introduttive. Se in effetti ci si limitasse all’imitazione pura e semplice dell’esatto comportamento della macchina, allora il lavoro eseguito per la simulazione di Enigma sarebbe più che sufficiente per realizzare la versione informatica. Tutta la fase preliminare all’impostazione dell’assetto delle varie Enigma coinvolte nella Bomba consisterebbe in poche fasi, da eseguire tutte manualmente. La prima 5 La “Bomba” di Turing: versione Informatica 29 sarebbe l’individuazione della posizione da far assumere al crib all’interno del testo cifrato manualmente. La seconda sarebbe la configurazione di una adeguato numero di Enigma secondo il numero di concatenazioni coinvolte nel crib, semplicemente attuabile mediante l’ausilio del metodo setOffset. La terza ultima fase consisterebbe infine nella verifica dell’assetto che realizzi la concatenazione per ciascuna delle 60 possibili disposizioni degli scambiatori negli alloggiamenti. Tuttavia si ritiene che la previsione di funzioni aggiuntive come l’individuazione automatica delle concatenazioni del crib, possa essere un aspetto non trascurabile. Nonostante il lavoro sia facilitato rispetto a come erano costretti a lavorare gli operatori di Bletchley Park, tale funzione non compromette in maniera eccessiva la fedeltà al funzionamento del simulatore anche perché, in fin dai conti, l’individuazione del posto ottimale in cui inserire il crib e il corrispettivo testo cifrato deve continuare ad essere fatto manualmente. Anche potendo prevedere un programma in grado di individuare tutte le posizioni valide del crib all’interno del testo cifrato, sarebbe sempre l’operatore umano a fornire alla macchina le informazioni aggiuntive per adottarne una in particolare (sempre prendendo ad esempio il crib wetter descritto in precedenza, un programma potrebbe individuare una sua possibile collocazione alla fine del crittogramma; ma ciò è ovviamente una semplice coincidenza in quanto i crittoanalsti saprebbero bene che la parola deve comparire in certe posizioni ben definite). Pertanto si è deciso di prevedere classi e funzioni con le seguenti funzioni: • Individuazione dell’allineamento ideale di un crib all’interno di un frammento di crittogramma. • Istanziazione automatica delle Enigma necessarie all’individuazione della chiave di messaggio. • Esecuzione della ricerca in parallelo di tutti gli assetti di scambiatori risolventi il problema. 5.2 Specifiche di oggetti e metodi 5.2.1 Classe EnigmaForAnalysis Si tratta di una sottoclasse della classe Enigma specificata in precedenza. Il motivo dell’estensione e dell’utilizzo dell’ereditarietà è presto detto: è necessario che la versione di Enigma per la crittoanalisi dei crittogrammi preveda delle particolari funzioni aggiuntive ed in particolare i metodi getCurrentConfig e addOffset. getCurrentConfig è un metodo che restituisce la configurazione attuale degli scambiatori di Enigma; questo metodo è necessario per facilitare il compito degli altri programmi che si poggiano su oggetti del tipo EnigmaForAnalysis, restituendo l’informazione sull’assetto attuale in una forma più gestibile come la stringa piuttosto che l’array di char. addOffset è un metodo che fa avanzare Enigma di un valore i passato come argomento; questo metodo è necessario per impostare la distanza che deve esistere tra gli assetti delle varie Enigma che compongono la bomba e deve ovviamente essere fatta mediante il metodo goNext ereditato dalla superclasse per consentire che si abbia l’avanzamento opportuno di tutti gli scambiatori nel caso sia raggiunto il limite dell’assetto (passaggio da Z ad A in uno degli scambiatori). 5 La “Bomba” di Turing: versione Informatica 5.2.2 30 Classe BadCribException Si tratta di una sottoclasse della classe Exception prevista dall’SDK Java che consente di gestire in maniera specifica il caso in cui sia stato passata, alla classe che si occupa dell’individuazione della posizione del crib nel crittogramma, una stringa che non produce concatenazioni. Vi è solo un costruttore che carica la variabile private msg con un valore passato come argomento e l’override del metodo toString. 5.2.3 Classe CribNode Si tratta della classe chiave per l’individuazione automatica delle concatenazioni. In sostanza individua l’esistenza di un ciclo e memorizza in una struttura dati ad albero tutte le possibili concatenazioni che si possono realizzare con il crib e il crittogramma passati come argomento. Esso si compone, per quanto riguarda i campi privati di: • chiaro: rappresenta qual’è il carattere in chiaro di partenza • cifra: rappresenta come il carattere in chiaro venga cifrato nel nodo corrente. • end: si tratta di una variabile di controllo; vale true se uno dei nodi figli del nodo corrente è raggiunto alla fine della ricerca ovvero se è riuscito a chiudere la concatenazione tornando al carattere di partenza; vale false su l’evetualità sopra descritta non si verifica. • offset: rappresenta la distanza dell’allinemento in esame da quello di partenza. • sons: si tratta della struttura dati a lista che contiene tutte le possibili concatenazioni che si possono realizzare a partire dall’allinemento corrente (per esempio se si considera il crib e il testo cifrato wetter e ETJWPX, risulta chiaro che se al primo ciclo la w viene crittata come E, al passaggio successivo è necessario verificare se la prima e di wetter, in posizione 2 nella parola, o la seconda, in posizione 5 nella parola, producano una concatenazione valida; è evidente che in questo caso solo la prima produrrà una concatenazione). • initChar: si tratta del carattere da cui si parte per generare le concatenazioni. È necessario per verificare, ad ogni generazione di figli, se si sia conclusa la ricerca di una concatenazione. Le specifiche dei metodi sono le seguenti: • CribNode (costruttore): ricevuti in ingresso un array di char che rappresenta il crib ed un array di char che rappresenta il crib cifrato inizializza cifra e chiaro secondo il valore di off passato come argomento e verifica, per ogni occorrenza di cifra adattato in minuscolo, se tale valore compaia nel crib passato come argomento. Se tale evenienza si verifica aggiunge alla lista dei figli tale occorrenza. Al termine del popolamento della lista dei figli inizializza il proprio campo di controllo end a seconda del fatto che uno dei propri figli abbia o meno completato la concatenazione con il crib passato e il corrispettivo ipotetico testo cifrato. 5 La “Bomba” di Turing: versione Informatica 31 • CribNode (costruttore): copia i valori del CribNode da copiare in quello corrente rendendo opinabile la copiatura della lista dei figli. Come già avvenuto nella presente documentazione si rimandano i restanti metodi alla lettura per la loro facilità di comprensione. 5.2.4 Classe CribNodeList È la classe utilizzata dalla classe precedente per implementare la lista dei figli. Prevede al suo interno una classe privata CribNodeListNode per memorizzare ogni singolo nodo in un oggetto separato che punta all’elemento successivo della lista. Le specifiche dei metodi sono le seguenti: • CribNodeList (costruttore): privo di argomenti, inizializza a null il valore del nodo radice. • CribNodeList (costruttore): avente come argomento un’altra CribNodeList, copia l’intero contenuto della lista passata nella lista corrente. • addNode: aggiunge un nodo in fondo alla lista corrente. • isClosedLoop: verifica se la lista corrente contiene dei nodi che chiudono la concatenazione, ovvero se esiste almeno un CribNode nella lista corrente che restituisca true quando gli viene applicato il metodo getEnd. • getPossibleWays(statico): conta, passato come argomento un CribNode, quante sono le concatenazioni chiuse che produce tale nodo. Per ogni figlio del nodo applica ad esso getPossibleWays, sommando tutti i risultati possibili. Se un nodo terminale (privo di figli) ha chiuso il cilo viene ritornato un 1, in caso contrario uno 0. • toCribNodeArray: converte la lista corrente in un array di CribNode. • getValidLoop(statico): passato come argomento un CribNode, restituisce una lista contenente la prima concatenazione di nodi producente un ciclo valido (quindi chiuso) a partire dal nodo passato come argomento ed analizzando le caratteristiche dei figli. Come già avvenuto nella presente documentazione si rimandano i restanti metodi alla lettura per la loro facilità di comprensione. 5.2.5 Classe CribTree Rappresenta l’oggetto unico che raccoglie un’unico CribNode radice da cui dipartono tutti i figli in cui si verifica la concatenazione, costruendo una vera e propria struttura ad albero n-ario variabile. I metodi implementati consistono semplicemente nell’applicazione dei metodi statici della classe CribNodeList al nodo radice. 5 La “Bomba” di Turing: versione Informatica 5.2.6 32 Classe Bomb È una classe che rappresenta un unica bomba di Turing che verifica gli assetti degli scambiatori realizzanti una concatenazione per una singola disposizione di scambiatori. Si compone di un certo numero di campi privati: • crib: è il crib che si presume comparire nel testo cifrato codedCrib. • codedCrib: è il testo cifrato in si presume si trovi la variabile crib. • enigmas: è i vettore di EnigmaForAnalysis che saranno configurate secondo le concatenazioni possibili di crib in codedCrib individuate dalla presente classe. • vett: è il vettore di CribNode che contiene le configurazioni necessarie per inizializzare l’array enigmas e per verificare di aver individuato l’assetto corretto. • offset: rappresenta la distanza del crib passato come argomento dall’inizio del testo cifrato, da considerare nel momento in cui si produce l’elenco degli assetti risolventi il crittogramma. • scambUsed: contiene il vettore degli scambiatori utilizzati con corrispettivo codice. • possibleRes: istanza della classe ArrayList prevista nello SDK per immagazzinare tutti gli assetti risolventi il crittogramma. Per quanto riguarda i metodi previsti, ecco le loro specifiche: • Bomb(costruttore): accetta come argomenti il crib di partenza, il testo cifrato in cui si presume essere contenuto il crib, la disposizione degli scambiatori e l’offset iniziale. Dopo aver inizializzato le variabili necessarie, richiama il metodo privato configure, per popolare vett con una concatenazione valida (se presente nel codedCrib). In caso vett rimanga pari a null (ovvero nel caso il crib nel codedCrib non produca alcuna concatenazione o nel caso siano state passate stringhe vuote) viene lanciata un’eccezione BadCribException, in caso contrario si procede all’inizializzazione del vettore enigmas secondo le caratteristiche della concatenazione, memorizzate in vett. • configure: verifica se il crib corrente possa produrre concatenazioni in codedCrib. Nel caso i due vettori siano di lunghezza uguale allora viene richiamato il metodo normalConfiguration. In caso contrario si tentano tutti gli allineamenti possibili di crib in codedCrib validi (che ovvero non contengono lettere alfabetiche uguali in corrispondenza dei medesimi indici) e per ciascuno si verifica la chiusura della concatenazione. • normalConfiguration: accetta due array (il crib e il testo cifrato corrispondente) oltre che un intero, per sapere a che distanza collocare il crib, e verifica se uno degli alberi generati a partire da ciascun allineamento produca un ciclo chiuso. In caso affermativo carica vett con tale ciclo chiuso altrimenti lo lascia con valore null. 5 La “Bomba” di Turing: versione Informatica 33 • find: testa tutte i 17.576 possibili assetti al fine di verificare se uno di essi realizzi la concatenazione che è memorizzata in ciascun nodo presente in vett. Nel caso ne venga trovata una che chiuda il ciclo, il numero dell’assetto corrente viene convertito nell’assetto in lettere dal metodo numberToAlfaConversion e immagazzinato nell’ArrayList possibleRes. • printSequence: restituisce una stringa in cui sono specificate l’indice di partenza della concatenazione (ovvero quale lettera in codedCrib rappresenta l’inizio della concatenazione) e la sequenza di concatenazioni tra lettere memorizzate in vett. • getResults: viene restituito un array di stringhe in cui sono memorizzati tutti gli assetti immagazzinati in possibleRes. • getArray: restituisce la copia dell’array contenente l’assetto degli scambiatori analizzato dalla bomba corrente. • alfaToNumberConversion(statico): converte una stringa di 3 caratteri alfabetici nell’indice corrispondente all’assetto di Enigma ad essa relativo. È come se venisse fatta una conversione da un numero espresso in base 26 (in cui i simboli sono a,b, ..., z) in un numero in base 10. • numberToAlfaConversion(statico): converte un numero nell’assetto corrispondente di Enigma ad esso relativo. Funzione inversa del metodo precedente, converte un numero espresso in base 10 in un numero espresso in base 26 con i simboli specificati in precedenza. • notEqualsCharArray(statico): restituisce true se i due array passati come argomento contengono diversi valori alfabetici in corrispondenza dei medesimi indici, false se c’è almeno un indice in cui i valori alfabetici sono uguali. 5.2.7 Classe BombRunner Classe wrapper della classe Bomb per rendere possibile l’esecuzione in multithread del metodo find. Implementa l’interfaccia Runnable per rendere possibile la parallelizzazione mediante oggetti di tipo Thread ed effettua l’unboxing dei metodi contenuti nell’oggetto Bomb istanziato al suo interno. 5.2.8 Classe AlanTuringBombs Rappresenta la realizzazione informatica di «Agnes» ovvero la bomba creata ed immaginata da Turing che verifica tutte le disposizioni di Scambiatori possibili. In sostanza una volta istanziato un oggetto di questa classe vengono create tante variabili di tipo BombRunner quante sono le disposizioni possibili di 5 scambiatori in 3 alloggiamenti (60 in tutto), le quali poi, mediante il metodo startThemAll, individueranno tutti gli assetti risolventi il crittogramma. Le variabili private con le loro funzioni sono le seguenti: • threads: l’array di BombRunner in cui verranno immagazzinate tutte le bombe necessarie a verificare ciascuna disposizione. • crib: la stringa che rappresenta il crib. 5 La “Bomba” di Turing: versione Informatica 34 • codedCrib: la stringa che rappresenta il testo cifrato in cui si presume essere memorizzato il crib. • initOffset: la distanza del codedCrib dall’inizio della cifratura di cui tenere conto nel momento in cui si restituisce l’assetto risultante (operazione fatta dalle singole Bomb). Invece, i metodi sono i seguenti: • AlanTuringBombs(costruttore): verifica se siano state passate stringhe vuote per generare una BadCribException e solo una volta estinto tale pericolo inizializza tutte le variabili precedentemente descritte usando il metodo disposizioni per generare ciascuna disposizione di 3 elementi in un set di 5. • startThemAll: genera un Thread per ogni BombRunner inizializzato nel costruttore e li fa partire in parallelo. Prima di terminare l’esecuzione applica il metodo join per assicurare che l’elaborazione abbia avuto termine. • getSolverResult: produce l’array di stringhe in cui sono memorizzati tutti gli assetti risolventi il crittogramma relativamente all’i-esima Bomba. • fact(statico): restituisce il fattoriale di un numero passato come argomento. • disposizioni(statico): genera l’i-esima k-permutazione (disposizione n,k con n pari alla dimensione di base) del vettore di array base. • getSequence: restituisce il ciclo relativo alla prima BombRunner (equivalente a tutte le altre) secondo la semantica già descritta. 5.2.9 Classe AlanTuringBombSimulator Interfaccia grafica in swing che realizza la simulazione della crittoanalisi dei crittogrammi enigma inseriti. L’interfaccia grafica si compone di: • 2 Aree di testo(Crib in chiaro, Testo cifrato): per inserire il crib e il testo cifrato che dovrebbe contenerlo. • 1 Pulsante (Trova): che istanzia l’oggetto AlanTuringBombs con il crib e il testo cifrato indicati nelle due aree di testo. • 1 Casella Combinata (Scambiatori): rappresenta ciascuna delle possibili disposizioni che assumono gli scambiatori (essendo caricate alla stessa maniera della Bomb è sufficiente utilizzarne l’indice relativo per sapere a quale disposizione si sta facendo riferimento). • 1 Campo di Testo (Assetti Validi): recherà la concatenazione individuata dal programma rispetto al crib in chiaro e al testo cifrato inseriti. • 1 Lista: indicherà ciascuno degli assetti risolventi il crittogramma. 5 La “Bomba” di Turing: versione Informatica 35 Il sorgente è abbastanza chiaro nelle sue funzioni (anche perché la semantica di ciascun componente è già stata descritta). Tuttavia si ritiene necessario chiarire ciò che è stato fatto per la gestione della pressione del pulsante Trova e il cambiamento del valore memorizzato nella casella combinata Scambiatori. • Trova: normalizza il contenuto delle due aree di testo secondo le regole specificate in Enigma per il testo chiaro e quello cifrato, dopodiché istanzia il campo privato theBomb di tipo AlanTuringBombs secondo il contenuto aggiornato delle due aree di testo. Nel caso venga generata un eccezione di tipo BadCribException (perché il contenuto delle aree è assente o perché il crib e il testo cifrato inseriti non producono concatenazioni) viene visualizzata una finestra di dialogo scomparsa la quale viene svuotato il contenuto del componente lista. In caso ciò non si verifichi, ovvero in caso ci sia una concatenazione, vengono lanciati i thread di theBomb e infine caricati nella lista i risultati relativi al valore corrente della casella combinata. • Scambiatori: se si è istanziata la variabile oggetto theBomb, la lista viene caricata con l’elenco dei risultati prodotti per il valore relativo alla nuova disposizione selezionata nella casella combinata. Riferimenti bibliografici [1] Codici & Segreti “La storia affascinante dei messaggi cifrati dall’antico Egitto ad Internet” - Simon Singh - Biblioteca Universale Rizzoli - 2005 [2] Enigma Machine - http://en.wikipedia.org/wiki/Enigma_machine [3] CryptoAnalysis of the Enigma - http://en.wikipedia.org/ wiki/Cryptanalysis_of_the_Enigma [Nota 1] Prodotti software usati per realizzare i programmi: “NetBeans 6.5” [Nota 2] Prodotti software usati per realizzare la presente documentazione: “Lyx version 1.6.2 Copyright 1995 by Matthias Ettrich” [Nota 3] I testi descrittivi relativi al funzionamento di Enigma sono stati liberamente tratti e riadattati dal libro Codici & Segreti [Nota 4] Le immagini della presente documentazione sono stati digitalizzati dal libro Codici & Segreti e tratti da en.wikipedia.org [Nota 5] Il codice sorgente del progetto in esame è liberamente consultabile all’indirizzo “http://code.google.com/p/iiwwcryptography/”