la sicurezza informatica

Transcript

la sicurezza informatica
CASTIGLIONI MARCO
POZZETTI MIRKO
TREVISAN MATTEO
LA SICUREZZA
INFORMATICA
ANNO SCOLASTICO 2001/2002
CLASSE 5IB
Sommario
SOMMARIO
Introduzione
III
Capitolo 1 La storia
1.1
La nascita dei calcolatori
1.1.1 I computer e la seconda guerra mondiale
1.1.2 I computer nel dopoguerra
1.1.3 I computer moderni
1.2
I computer nella seconda guerra mondiale
1
1
2
3
4
Capitolo 2 Il presente
2.1
Le comunicazioni in Internet
2.2
Il protocollo IP
2.2.1 Il preambolo IP
2.2.2 Struttura dell’indirizzo IP
2.3
Il protocollo TCP
2.3.1 Il preambolo TCP
2.3.2 Gestione delle connessioni TCP
2.4
Le porte
2.4.1 Esempi di porte
2.5
I socket
2.6
Esempi
2.6.1 Tracert
2.6.2 Netstat
7
8
8
10
11
12
13
15
16
17
17
18
18
Capitolo 3 La crittografia
3.1
La storia
3.1.1 Crittografia antica
3.1.2 Crittografia fino al XVIII secolo
3.1.3 Crittografia moderna
3.2
Principali cifrari
3.2.1 Cifrari a sostituzione
3.2.2 Cifrario affine
3.2.3 Cifrario Playfair
3.2.4 Stream cypher
3.2.5 Cifrario di Vernam
3.3
La sicurezza perfetta
3.4
Gli algoritmi
3.4.1 Il DES
3.4.2 L’ RSA
3.5
Macchine cifranti
3.5.1 Enigma
3.5.2 La bomba di Turing
3.6
Crittoanalisi
3.6.1 Crittoanalisi statistica
3.6.2 Crittoanalisi lineare
3.6.3 Crittoanalisi differenziale
3.6.4 Crittoanalisi su polialfabetici
3.6.5 Brute force
3.7
Curiosità e considerazioni
19
21
23
25
28
28
28
30
31
32
33
35
35
45
46
46
52
57
57
58
60
60
61
62
I
Sommario
Capitolo 4 Esempi pratici
4.1
L’uso di Winsock
4.1.1 Struttura dell’applicazione
4.1.2 Implementazione dell’applicazione
4.2
Il DES
4.2.1 La classe CDes
4.3
Scambio di messaggi crittati
4.3.1 Struttura dell’applicazione
4.3.2 Implementazione dell’applicazione
4.4
L’ analisi di un testo
4.4.1 Struttura dell’applicazione
4.4.2 Implementazione dell’applicazione
4.5
I socket in Linux
4.5.1 Implementazione dell’applicazione
4.6
PGP
64
64
66
68
68
75
76
76
78
78
81
88
88
90
Conclusioni
101
Appendice A
105
Appendice B
109
Appendice C
114
Appendice D
120
Appendice E
121
Appendice F
123
Glossario
171
Bibliografia
176
II
Introduzione
INTRODUZIONE
L’ argomento trattato nell’ area di progetto, la sicurezza
informatica, è entrato in auge in seguito alla capillare di
diffusione dei PC e di Internet. Con essi sono nati i primi seri
problemi di sicurezza sia per i privati e, soprattutto, per le
grandi aziende.
Nell’area di progetto si è cercato di analizzare questo
problema prendendo in esame sia la parte teorica che quella
pratica.
In particolare l’attenzione è stata focalizzata su i due
grandi temi chiave della sicurezza : gli attacchi via socket e la
crittografia. Infatti sono questi i due temi che ad oggi
determinano o meno la sicurezza di un sistema. Il primo, cioè i
socket, riguarda la trasmissione delle informazioni, il secondo,
la crittografia, riguarda la sicurezza intrinseca di esse.
La trattazione di questi argomenti nella parte pratica ha
permesso di realizzare una piccola applicazione che è in grado,
tramite l’uso congiunto di socket e crittografia, di inviare
messaggi cifrati tra due stazioni.
Inoltre è stata realizzata una piccola applicazione che
permette di crittare i messaggi attraverso algoritmi “storici”
come la scacchiera di Polibio o il cifrario di Cesare.
Come ultimo esempio pratico è stato analizzato l’uso di
PGP. In pratica è stato costruito un piccolo manuale,
contenente le istruzioni più importanti, per usare il programma
di crittazione più diffuso al mondo.
La seconda parte dell’area di progetto si basa sulle
conseguenze che l’azione congiunta di informatica e crittografia
hanno portato nella storia. In particolare si analizzeranno le
tecniche usate nella seconda guerra mondiale per cifrare le
informazioni, come la macchina Enigma e quelle per decifrarle,
come la Bomba di Turing.
In particolare lo sviluppo della crittografia è stato
affrontato fin dai primi algoritmi (codice Atbash) fino ad
arrivare ai giorni nostri.
III
La storia
Capitolo 1
La storia
1.1
1.2
1.1
La nascita dei calcolatori
1.1.1 I computer e la seconda guerra mondiale
1.1.2 I computer nel dopoguerra
1.1.3 I computer moderni
I computer nella seconda guerra mondiale
La nascita dei calcolatori
La parola computer deriva dal latino “computare” che
significa “fare di conto”.
Questo strumento è nato per facilitare il calcolo di
funzioni matematiche complesse. Già nel 1642 il matematico
Blaise Pascal inventò e costruì la prima calcolatrice macchina
con riporto automatico con otto cifre. Questa macchina servì
solo a dimostrare che si potevano eseguire calcoli matematici
anche con macchine e non solo con la mente, mentre il vero e
proprio computer nasce solo nel XX secolo. Sempre in questi
anni nasce la scienza dell’informatica, che studia l’elaborazione
dei dati e il trattamento automatico delle informazioni.
1.1.1
I computer e la seconda guerra mondiale
Il secondo conflitto mondiale fu la rampa di lancio dei
primi computer, che furono ideati sia dalla parte alleata sia dalla
parte tedesca.
I tedeschi furono i primi a costruire un macchina che fu in
grado di generare un codice crittato, che era incomprensibile per
gli alleati. Questo codice, creato dai tedeschi per comunicare
strategie di guerra e messaggi, fu incomprensibile per gli alleati
per tutta la prima parte del conflitto.
Churchill incaricò il matematico inglese Turing, che fu
l’ideatore della prima macchina, che era in grado di leggere le
informazioni da un nastro e di copiarle su un altro, di dirigere il
centro di studi sulla comunicazione.
Turing formò un gruppo di lavoro per decifrare i codici
crittati, formato da circa settemila persone, sia militari sia
personale civile (si andava da matematici, ad archeologi, a
crittografici, ad enigmisti, a giocatori d’azzardo e a tante altre
persone).
Ma solo un esperto di centralini telefonici ideò il primo
calcolatore elettromeccanico, che era in grado di trovare in
pochi minuti i codici nazisti: questa macchina prese il nome di
Colossus.
1
La storia
Questo calcolatore cambiò letteralmente le sorti della
guerra, infatti, gli alleati erano in grado di prevedere le mosse
dei tedeschi e la marina italiana ne fece le spese, venendo
sconfitta nel 1941 a Capo Matapan.
Alla fine della seconda guerra mondiale Churchill ordinò
di smantellare tutti gli esemplari di Colossus.
1.1.2
I computer nel dopoguerra
Gli anni del dopoguerra furono fondamentali per la
nascita di calcolatori più veloci, anche se questi calcolatori
“moderni” erano molto grossi, pesanti e lenti rispetto a
quelli che usiamo ora.
Il primo calcolatore elettromeccanico funzionava
automaticamente con programmi registrati (che sono gli
“antenati” dei primi software).
Il nome di questo calcolatore era Harvard Mark 1 e fu
realizzato nei laboratori dell’IBM, in collaborazione con
l’università di Harvard. Con questo calcolatore è nato anche
il termine “bug”, che viene utilizzato dagli specialisti per
definire un errore.
Il calcolatore Bessie che eseguiva operazioni
matematiche come la somma di numeri a 23 cifre in tre
decimi di secondo e una moltiplicazione in 6 secondi, venne
impiegato dalla marina militare statunitense per studi sulla
balistica e progettazione di navi. Inoltre venne anche usato
dalla commissione dell’energia per ricerche sulla
disintegrazione dell’atomo.
Un altro calcolatore realizzato nel 1946, destinato
solamente ad un uso militare, chiamato Eniac, costò la
bellezza di mezzo milione di dollari di allora. Questo
calcolatore serviva per il calcolo delle traiettorie dei
proiettili. Esso riusciva a realizzare una tabella balistica in
30 minuti contro le 20 ore impiegate da un uomo. Questo
calcolatore fu tenuto in funzione solo per nove anni, dopo
di che non fu più utilizzato poiché aveva un alto costo di
manutenzione. Esso va ricordato anche per un altro fatto:
durante la sua creazione lo scienziato John Tykey creò il
termine “bit”, contrazione delle parole “Binary DigiT”. Esso
rappresenta la più piccola unità di informazione, che
specifica due stati: 1 (acceso) e 0 (spento), che codificano i
dati all’interno di un computer. Una striscia di otto bit
forma un “byte”, che oggi viene utilizzato per rappresentare
un carattere o un singolo numero.
Nel 1947 fu inventato il transistor, il quale
rivoluzionò completamente il mondo del computer. Questi
dispositivi erano molto più piccoli (qualche millimetro)
rispetto alle valvole (diversi centimetri), erano molto più
resistenti e consumavano molta meno elettricità.
Fino al 1950 i computer non avevano memoria e quindi
le informazioni non potevano essere salvate. Tra il 1950 e il
2
La storia
1955 i calcolatori vennero dotati di memorie, ma la capacità
di memorizzazione era solo di un bit alla volta. Queste
memorie “interne” erano molto ingombranti e siccome i
computer avevano già grandi dimensioni, si decise di
abbandonarle, puntando su memorie ausiliarie o esterne,
come nastri e dischi magnetici.
Negli anni successivi si costruirono calcolatori sempre
più piccoli, arrivando nel 1957 alle dimensioni di un
frigorifero. Questo calcolatore era accessibile solamente
all’esercito. Ma l’era dei computer domestici era lontana,
poiché il costo era elevato e le dimensioni non certo adatte
per una casa.
Ma la vera rivoluzione avvenne nel 1958, grazie
all’ingegnere americano Kilby che inventò i circuiti
integrati.
1.1.3
I computer moderni
Gli integrati rivoluzionarono il mondo del computer:
con questa invenzione i calcolatori potevano avere delle
dimensioni molto ridotte rispetto ai loro predecessori.
Questa invenzione nel campo informatico prese il nome di
chip. I computer ebbero una diffusione maggiore: essi non
solo potevano essere acquistati dai militari, ma anche da
industrie. Erano molto veloci, grazie a questi circuiti
miniaturizzati, ma il loro costo era molto elevato e ancora
accessibile a pochi.
Questi computer erano prodotti soprattutto in
America, ma nel 1965 anche l’Italia scese in campo, grazie
all’ Olivetti, che costruì un calcolatore chiamato
“Programma 101”, che ebbe grande successo, soprattutto
oltreoceano. Questo calcolatore fu il primo ad avere
memorizzato al suo interno un programma ed un supporto
magnetico, dal quale avrà origine il “floppy disk”.
Nel 1968 l’industria americana prese il sopravvento,
infatti, in questo anno nacque l’Intel, che fu ed è tuttora,
l’azienda leader nella costruzione di processori e chip di
memoria.
Nel 1970 costruì la prima RAM adottata da tutti i
calcolatori al posto delle vecchie memorie a nuclei
magnetici.
Nel 1971 venne costruita la prima cpu che da allora,
costituisce il cuore del calcolatore. Essa era in grado di
tenere memorizzati i dati, fino a che non veniva a mancare
la corrente.
Per realizzare il computer come lo conosciamo oggi,
mancava ancora un componente, infatti, il vero problema era
memorizzare i dati all’interno del calcolatore, senza perderli
una volta tolta la corrente. Questo problema venne superato
grazie al primo “hard disk”, costruito dall’IBM, che
3
La storia
permetteva di immagazzinare i dati anche in mancanza di
corrente.
La data più importante nella storia dei computer e
dell’informatica fu il 1975, anno in cui, grazie a due studenti
universitari, William “Bill” Gates e Paul Allen, nacque la
Microsoft, prima azienda specializzata nell’elaborazione di
linguaggi per computer. A questa azienda si opposero altri
due giovani, Stephen Jobs e Stephen Wozniak, che nel
salotto della loro casa, costruirono Apple I e diedero vita
nel 1976 alla Apple azienda, tuttora in competizione con
Microsoft. Nel 1977, Jobs e Wozniak, costruirono Apple II,
che era solo dotato di una tastiera, di un alimentatore e di
prese per il collegamento con le periferiche, già presenti sul
mercato.
Nel 1981 l’IBM, che allora era la maggiore produttrice
di computer, investì sulla produzione dei “Personal
Computer” grazie anche all’aiuto della Microsoft, la quale
ideò e fornì il primo sistema operativo : l’ MS-DOS, che è
tuttora utilizzato.
In questi quarant’ anni il computer si è evoluto
rapidamente, passando dall’essere lento e ingombrante ad
avere dimensioni che siamo abituati a vedere tutti i giorni e
a velocità che sono in costante aumento.
Nel futuro i computer saranno sempre più piccoli e
più veloci e faranno sempre più parte della nostra vita
quotidiana.
1.2
I computer nella Seconda Guerra Mondiale
Dopo l’ascesa al potere di Hitler, verificatasi in Germania
a partire del 1933, e la costruzione del suo regime dittatoriale, il
nazismo portò prima l’Europa e poi il mondo intero in un nuovo
e spaventoso conflitto mondiale.
La guerra iniziò il 1° settembre del 1939 con l’attacco
della Germania alla Polonia che venne conquistata i poche
settimane . Il 3 settembre la Francia e l’Inghilterra dichiararono
guerra alla Germania.
Mentre sul fronte francese non si verificarono inizialmente
combattimenti, la Russia attaccò e conquistò la Finlandia, la
Germania per stringere l’Inghilterra in una morsa attaccò e
conquistò la Danimarca e la Norvegia. Sulla linea di confine tra
Francia e Germania i francesi costruirono una linea difensiva
(Linea Maginot), con trincee e cannoni, che serviva come difesa
in caso di attacco, ma la Germania attaccò, passando per il
Belgio, il 10 maggio del 1940, e dopo poco più di un mese i
tedeschi conquistarono gran parte della Francia.
Il 10 giugno del 1940 entrò in guerra a fianco dei nazisti
l’Italia. Con questo intervento militare si verificherà la
conquista italiana di territori in Africa (Somalia, Sudan) e della
Grecia, mentre perdette l’Etiopia; inoltre subì gravi sconfitte
navali a Punta Stilo e a Capo Matapan nel 1941, derivanti dalla
4
La storia
superiorità della marina inglese, ottenuta grazie al radar. La
battaglia di Capo Matapan fu persa a causa dell’intercettazione
inglesi delle trasmissione crittate tra Italiani e tedeschi, grazie al
primo computer COLOSSUS.
Per l’Asse (Germania, Italia, Giappone) fino alla fine del
1941 la guerra portò importanti vittorie, che rafforzarono il loro
potere e permisero la conquista di nuovi territori e, come
conseguenza, l’allargamento dei propri confini.
I tedeschi evitarono che i paesi alleati ricevessero gli aiuti
dagli Stati Uniti; questi ultimi si dichiararono neutrali nel 1939
insieme al Giappone. Ma gli USA, in realtà, fornivano aiuti ai
paesi che non avevano al potere dei regimi totalitari filo fascisti. I tedeschi cercarono di evitare che gli aiuti statunitensi
raggiungessero l’Europa, usando i sottomarini (U-boat), che
aspettavano le navi al largo dell’Atlantico e le affondavano.
I sottomarini tedeschi, riuscivano a comunicare tra di loro
e con gli alti comandi dell’esercito tramite l’invio di messaggi.
Questi ultimi per non essere intercettati e capiti dagli Alleati
erano crittati con la macchina ENIGMA. Per la prima parte della
guerra le potenze dell’Asse riuscirono a comunicare con
sicurezza senza che gli Alleati riuscissero a intercettare e a
comprendere i messaggi mandati.
Con l’attacco della Germania alla Russia, che iniziò nel
giugno del 1941, cominciò il declino delle potenze dell’asse.
Dopo aver riportato vittorie schiaccianti in pochi mesi,
l’immenso esercito arrivò alle porte di Mosca e Stalingrado. Ma
con l’inizio dell’inverno la macchina bellica si inceppò, fermò
la sua marcia verso la conquista dell’intero territorio e cominciò
una guerra di posizione,. L’esercito russo si riorganizzò e sferrò
la controffensiva, mentre quello tedesco arretrò per circa 200
chilometri. Come conseguenza Hitler ordinò la resistenza a
oltranza e nel giugno del 1942 dispose di radere al suolo
Stalingrado, ma l’esercito non riuscì nell’impresa; questo fu
l’inizio della fine per le potenze dell’Asse.
Inoltre gli Alleati riuscirono a rompere il codice crittato
che permetteva ai tedeschi di comunicare segretamente, così da
permettere agli alleati di conoscere in anticipo le mosse del
nemico.
Questa rottura del codice fu effettuata da un gruppo di
persone aiutate da un computer chiamato COLOSSUS. Questo
gruppo fu incaricato da Churchill sotto la supervisione di Alan
Turing.
Anche sul fronte del Pacifico cominciarono a verificarsi le
prime sconfitte del Giappone da parte degli americani.
Come già stato detto, sia i giapponesi che gli americani, si
dichiararono neutrali nel 1939, ma dopo l’attacco nipponico a
Pearl Harbor, avvenuto il 7 dicembre 1941, gli USA decideranno
di entrare in guerra. Nel Pacifico la forza americana era
gravemente indebolita, poiché l’attacco a Pearl Harbor riportò
gravi perdite di uomini e mezzi, rendendo le forze giapponesi
superiori. Per avere il predominio nel Pacifico e l’annientamento
5
La storia
della flotta americana, i giapponesi dovettero organizzare un
nuovo attacco.
L’intelligence navale degli Stati Uniti aveva subito un
grave smacco nell’attacco alle Hawaii, ma si misero al lavoro per
cercare d’intercettare e decrittare il messaggi nipponici; fu
formato così un gruppo composto per la maggior parte
d’analisti. In 6 mesi di lavoro furono in grado di decrittare il
codice. Da questo momento, gli americani poterono sapere in
anticipo le mosse del nemico, ma non dove sarebbe avvenuto
l'attacco. Il luogo scelto dai giapponesi furono le isole Midway,
che fu scoperto casualmente in un messaggio cifrato. Il 4 giugno
del 1942 iniziarono le prime schermaglie: sia i giapponesi che gli
americani persero un numero uguale di navi, ma il contrattacco
portato dagli americani fu schiacciante e vennero distrutte la
maggior parte delle portaerei giapponesi, mentre le forze aeree
vennero decimate. Dopo la schiacciante vittoria, le forze nel
Pacifico tornarono in parità.
Da questo momento la macchina industriale americana
cominciò a produrre navi e mezzi per combattere il Giappone.
A patire dal 1943 i giapponesi persero la maggior parte dei
territori, gli americani si avvicinarono pericolosamente alle
coste del giappone. Nel 1944 cominciarono i bombardamenti su
Tokyo.
Ma la vera forza nipponico era basata sull’esercito di terra.
Allora Truman decise di sganciare due bombe atomiche sul
Giappone per mettere fine al conflitto.
Ne 1943 gli alleati sbarcarono in Italia e Mussolini venne
arrestato e imprigionato. Si istituì il governo di Badoglio. Il 5
maggio del 1944 gli alleati conquistarono Roma.
Gli alleati e l’Unione Sovietica decisero di aprire un nuovo
fronte di guerra: il luogo scelto fu la Normandia. La sbarco
riuscì con successo e sia l’esercito alleato, sia i sovietici
marciarono inarrestabili verso la Germania e Berlino. Il 7
maggio i tedeschi firmano la capitolazione.
6
Il presente
Capitolo 2
Il presente
2.1
2.2
2.3
2.4
2.5
2.6
2.1
Le comunicazioni in Internet
Il protocollo IP
2.2.1
Il preambolo IP
2.2.2
Struttura dell’indirizzo IP
Il protocollo TCP
2.3.1
Il preambolo TCP
2.3.2
Gestione delle connessioni TCP
Le porte
2.4.1
Esempi di porte
I socket
Esempi
2.6.1
Tracert
2.6.2
Netstat
Le comunicazioni in Internet
La maggior parte delle applicazioni che comunicano via
rete (Internet o LAN) utilizzano gli stessi principi.
Vi è una stazione cliente (client) che richiede un servizio
ad una stazione servente (server). Quest’ ultima rimane in
ascolto fino a che il cliente non richiede un servizio. A questo
punto la stazione servente può decidere o meno di esaudire la
richiesta. In caso affermativo le due stazioni cominciano a
scambiarsi informazioni, il canale di comunicazione è
bidirezionale, ovvero entrambe le stazioni possono inviare
informazioni. Quando le due stazioni hanno terminato di
comunicare la comunicazione verrà abbattuta.
Quella appena fatta è una descrizione semplificata del
protocollo TCP/IP (Transfer Control Protocol/Internet
Protocol), il principale protocollo di comunicazione usato in
Internet.
La sua principale funzione è quella di fornire un flusso
affidabile di dati tra due stazioni e permettere l’identificazione
di esse tramite un indirizzo.
Il TCP/IP nasce durante gli anni ’70, congiuntamente con
la versione 3.4 di UNIX. Il progetto fu elaborato dall’università
californiana di Berkeley.
Il suo sviluppo è stato reso necessario dalla nascita delle
prime reti a commutazione di pacchetto, avvenuta durante gli
anni ’60. La prima di esse fu ARPANet, nata da uno studio
finanziato dall’agenzia americana DARPA (Defense Advanced
Research Project Agency) e svolto dall’ARPA (Advanced
Research Project Agency).
7
Il presente
Durante gli anni ’80 con la fusione tra ARPANet e
NSFNET (National Science Foundation NETwork) nasce la rete
mondiale Internet, la quale verrà aperta al pubblico da 1992.
2.2
Il protocollo IP
Il protocollo IP (Internet Protocol) appartiene al livello 3°
(livello di rete) del sistema a strati OSI (Open System
Interconnection, standard internazionale per l’organizzazione di
reti locali) e consente l’implementazione di una rete a
commutazione di pacchetto che può utilizzare qualunque DLC
(Data Link Control). Esso spedisce le informazioni divise in
pacchetti, e ognuno di essi percorre diversi percorsi attraverso
la rete. Quindi non si garantisce che il primo pacchetto inviato
sia anche il primo arrivato al ricevitore. Per compensare questo
difetto si utilizza il protocollo TCP che appartiene al 4° livello
OSI (livello di trasporto) che garantisce l’ordine dei pacchetti
arrivati al terminale attraverso l’IP e assicura l’affidabilità del
protocollo.
Ogni interfaccia su una rete TCP/IP riceve un
identificatore univoco chiamato indirizzo IP. Ad ogni periferica
della rete verrà assegnato un indirizzo IP. Ogni computer
possedente un indirizzo IP e capace di comunicare via TCP/IP
viene chiamato host. Esso possiede almeno una scheda di rete o
un modem. Di conseguenza, se un host possiede più schede di
rete, possiederà anche più indirizzi IP.
Gli indirizzi IP sono formati da due parti : un ID di rete e
un ID dell'host.
L'ID dell'host identifica un singolo host che si trova su un
segmento di rete. L'host può comunicare direttamente solo con
altri host che si trovano sullo stesso segmento di rete, infatti, i
segmenti, sono divisioni logiche di una rete in univoci ID
numerici chiamati subnet.
L'host deve usare, per comunicare con gli host di una diversa
subnet, un router che comunica con entrambe le subnet.
Il successo dell’IP è dovuto alla flessibilità, la quale
permette di connettere reti basate su tecnologie eterogenee.
2.2.1
Versione
Il preambolo IP
8
16
IHL
Tipo di servizio
Identificazione
Tempo di vita
24
32
Lunghezza del pacchetto
DF MF Offset di frammentazione
del pacchetto
Checksum
Protocollo
Indirizzo sorgente
Indirizzo destinazione
Options (lunghezza variabile)
8
Il presente
Version
Descrive la versione del protocollo utilizzato dal datagram
IPv4. La lunghezza è di 4 bit.
IHL
Siccome la lunghezza dell'header non è constante in questo
campo è contenuta la lunghezza dell'header in parole di 32 bit il
valore minimo è 5 (nessuna opzione header = 20 byte) il
massimo è 15 byte (header uguale a 60 byte). La lunghezza del
campo è di 4 bit.
Tipo di servizio
Consente agli host di comunicare alla rete il tipo di
servizio desiderato in base ai parametri: ritardo, capacità di
trasmissione affidabilità. La lunghezza è di 8 bit.
Lunghezza del pacchetto
Riguarda l'intero pacchetto la massima lunghezza è di
65.536 byte pari a 16 bit.
Identificazione
È necessario per permettere all'host di destinazione di
determinare a quale datagram appartiene un frammento appena
arrivato.Tutti i frammenti di un datagram contengono lo stesso
numero di identificazione. La lunghezza è di 16 bit.
Offset di frammentazione del pacchetto
Indica in quale posizione del datagram corrente si trova
questo frammento, tutti i frammenti tranne l'ultimo devono
essere multipli di 8 byte, il campo è di 13 bit , avrò quindi un
massimo di 8192 frammenti (8192 x 8 = 65536 byte al
massimo(IP packet).
Tempo di vita
È un contatore utilizzato per limitare il tempo di vita dei
pacchetti sulla rete. Quando il contatore raggiunge lo 0 il
pacchetto viene scartato e viene inviato alla destinazione un
messaggio di avvertimento. Lunghezza pari a 8 bit.
Protocollo
Campo che indica il protocollo che viene usato al livello
trasporto (TCP, UDP e altri) la numerazione dei protocolli è
globale ed è descritta nel RFC 1700. La lunghezza è di 16 bit.
Indirizzo sorgente e destinazione
Sono rispettivamente gli indirizzi del mittente e del
destinatario del pacchetto composti da 32 bit ognuno.
Checksum
Verifica solamente il preambolo IP. E’ utilizzato per
verificare gli errori generati dai router. L'algoritmo consiste nel
sommare tutte le parole di 16 bit che arrivano usando
9
Il presente
l'aritmetica di complemento a 1 e quindi prendendo il
complemento a 1 del risultato. Il risultato finale deve essere 0.
Da notare che l'algoritmo deve essere cambiato ad ogni salto
perchè c'è almeno un campo che cambia il TTL (time to live).
La seconda struttura illustra le opzioni che si possono
aggiungere a un pacchetto IP. Quelle più usate sono descritte di
seguito.
Security
Descrive il grado di segretezza delle informazioni, in
teoria un router militare dovrebbe utilizzare questo campo per
richiedere di non attraversare paesi considerati a rischio.
Strict source routing
Fornisce il percorso completo da seguire.
Loose source routing
Richiede che il pacchetto attraversi una lista di router
specificati nell'ordine specificato ma e' possibile che passi
attraverso altri router lungo il percorso.
Record route
Forza i router lungo il cammino ad aggiungere il loro
indirizzo IP al campo opzione.
Timestamp
È simile all'opzione record route a parte il fatto che oltre
a registare l'indirizzo a 32 bit ogni router regista un timestamp
di 32 bit (motivi diagnostici).
2.2.2
Struttura dell’indirizzo IP
L’indirizzo IP è composto da 4 byte (1 byte = 0 Æ 255
decimale o 0 Æ ff esadecimale) che identificano in modo
univoco un computer, quindi a ogni terminale corrisponde un
solo indirizzo IP.
Esempio
123.1.82.109
In una rete locale (LAN, Local Area Network) l’indirizzo
IP è statico. Il primo indirizzo è 192.168.0.1, gli altri indirizzi
crescono in modo sequenziale. Diversamente in Internet (WAN,
World Area Network) l’indirizzo IP è dinamico, quindi ad ogni
nuova connessione si avrà un nuovo IP. Questo avviene per
diversi motivi:
• primo, il totale degli indirizzi che si possono creare con
32bit è 4.294.967.296, quindi non è possibile applicare ad ogni
utente un IP fisso poiché gli indirizzi disponibili non sarebbero
sufficienti;
• secondo, un IP statico faciliterebbe il compito ai pirati
informatici
10
Il presente
Poiché esistono “solo” 4,3 miliardi di indirizzi IP gli
sviluppatori hanno deciso di suddividerli in 5 diverse classi,
dalla A alla E. Ognuna di esse ha un funzionamento diverso
dalle altre.
Per identificarle il 1° byte dell’IP ha dei valori diversi :
Classe
Configurazione binaria
del 1° byte
Indirizzo
Struttura
Classe A
Classe B
Classe C
Classe D
Classe E
0xxxxxxx
10xxxxxx
110xxxxx
1110xxxx
11110xxx
0-127.x.x.x
127-191.0-255.x.x
192-223.0-255.0-255.x
224-239.x.x.x
240-255.x.x.x
Net_Add 1°byte
Net_Add 1°, 2° byte
Net_Add 1°, 2°, 3° byte
Flat
Usi futuri
Naturalmente le varie classi hanno funzionalità diverse.
Le classi A, B, C hanno scopi commerciali ossia sono usate
da società o da privati per connettersi a Internet, mentre la
classe D è usata per impieghi speciali mentre la classe E è
riservata per usi futuri.
Le 3 classi per usi quotidiani hanno delle differenze
sostanziali, poiché hanno tutte un diverso numero di host e un
diverso numero di reti :
Classe
Numero di reti
Numero di host
Classe A
Classe B
Classe C
126
16.384
2.097.152
16.777.214
65.534
254
Si può notare che la classe A ha un elevato numero di
host, ma un basso numero di reti.
Al contrario la classe C può avere pochi host, ma un
elevato numero di reti.
Classe
Indirizzo IP
ID di rete
ID dell'host
Classe A
Classe B
Classe C
10.1.1.10
172.16.1.10
192.168.1.10
10
172.16.00
192.168.1
1.01.10
1.10
10
La scelta della classe dipende dalla rete che si vuole
effettuare.
2.3
Il protocollo TCP
Il protocollo TCP fa parte del 4° livello dello standard
OSI. Il suo compito è quello di rendere affidabile il protocollo
IP, fornendo una verifica sulla consegna dei dati. TCP
garantisce una consegna corretta per mezzo della ricevuta
positiva con ritrasmissione (PAR, Positive Acknowledgment with
Retransmission) e assembla nel corretto ordine i datagrammi IP
in cui è stato frazionato il messaggio, all’arrivo di esso al
ricevente.
11
Il presente
Il TCP è diviso in 4 livelli fondamentali :
7
4
3
1–2
Applicazione
Trasporto (TCP)
Internet (IP)
Host - rete
Livello di Trasporto
In questo particolare caso il livello di trasporto è
solamente il TCP, ma in generale potrebbe essere anche l’UDP.
Il TCP è un protocollo orientato alla connessione
affidabile, ossia assegna ai livelli superiori l’affidabilità che
invece manca al livello inferiore, ovvero all’IP.
Il protocollo TCP ha il compito di dividere il messaggio
entrante e passarlo al livello IP. Il datagramma di lunghezza
massima è di 65496 (65536 – 20 per il preambolo TCP – 20 per
il preambolo dell’IP).
Livello Internet
Il livello Internet è il fulcro, insieme al TCP,
dell’architettura.
L’indirizzo permette di inserire un pacchetto in una
qualsiasi rete( può essere una LAN, una MAN o Internet).
I pacchetti inviati possono arrivare in ordine diverso
rispetto a come sono partiti.
Lo scopo del livello Internet è consegnare i pacchetti IP al
luogo di destinazione.
2.3.1
Preambolo TCP
8
Source port
TCP
H.L.
URG ACK PSH
16
Sequence number
Acknowledgement Number
RST SYN FIN
Checksum
24
Destination port
32
Window size
Urgent pointer
Options (lunghezza variabile)
Data (lunghezza variabile)
Sorgente e destinazione
Rispettivamente porta sorgente e porta destinazione
identificano gli estremi locali di una connessione, ogni host
deve decidere come allocare le proprie porte successive alla 256.
Il punto di accesso del livello trasporto sarà quindi identificato
dall'indirizzo espresso nel seguente formato
ADDRESS IP : PORTA
La lunghezza di ambedue i campi è di 16 bit.
Numero di sequenza
Un numero di sequenza viene assegnato ad ogni pacchetto
durante la connessione tra 2 host, il campo è composto da 32
bit.
12
Il presente
Numero Ack
È uguale a 1 per indicare che il numero di ack è valido, se
ack = 0 il segmento non contiene ack e il campo numero di ack
viene ignorato.
PSH
Indica dati di tipo push, in questo modo si richiede al
mittente di consegnare i dati dell'applicazione al momento
dell'arrivo, evitando che siano salvati in un buffer di attesa.
Lunghezza 1 bit.
RST
Viene utilizzato per reinizializzare una connessione che è
diventata instabile a causa del guasto di un host o per qualche
altro motivo. Inoltre viene anche utilizzato per rifiutare
l'apertura di una connessione. Lunghezza 1 bit.
SYN
Viene utilizzato per creare una connessione. La richiesta
di connessione è caratterizzata da SYN=1 ACK=0. La risposta
sara' SYN=1 ACK=1. Lunghezza 1 bit.
FIN
Viene utilizzato per chiudere una connessione. Specifica
che il mittente non ha altri dati da spedire, tuttavia dopo aver
chiuso una connessione, un processo può continuare a ricevere
dati indefinitamente. Lunghezza 1 bit.
Window
Il controllo di flusso TCP è gestito utilizzando un
protocollo sliding window a dimensione variabile. Il campo
window specifica quanti byte possono essere spediti a partire dal
byte confermato. Lunghezza 16 bit.
Checksum
Per garantire l'affidabilità è presente anche un campo
checksum, che verifica il preambolo i dati e lo
pseudopreambolo. Quando viene eseguito il calcolo, il campo
checksum viene posto uguale a 0, e il campo dati viene
completato con un 0 se la lunghezza è un numero dispari.
L'algoritmo di checksum somma tutte le parole di 16 bit in
complemento a 1 e quindi prende il complemento a 1 della
somma. Come conseguenza quando il ricevente esegue il calcolo
sull'intero segmento (compreso il checksum) il risultato deve
essere 0.
2.3.2
Gestione delle connessioni TCP
In TCP, per creare una connessione viene usato il
protocollo three-way handshake che consiste, come indicato dal
nome, in tre passi principali :
13
Il presente
1.
2.
3.
il client spedisce un pacchetto TCP avente il flag
SYN impostato, il flag ACK non impostato e con
un valore X del sequence number;
il server risponde con entrambi i flag SYN e ACK
impostati, con il sequence number con un valore Y
e acknowledgment number con valore X+1;
il client risponde con il flag ACK impostato, con il
Sequence number con valore X+1 e
acknowldgement number con valore Y+1.
SYN=1 ACK=0 SEQ-NUM=X
CLIENT --------------------------------------> SERVER
SYN=1 ACK=1 SEQ-NUM=Y ACK-NUM=X+1
CLIENT <-------------------------------------- SERVER
ACK=1 SEQ-NUM=X+1 ACK-NUM=Y+1
CLIENT --------------------------------------> SERVER
Dopo che la connessione è stata inizializzata si può
procedere al trasferimento dei dati. In seguito verrà indicato
con pacchetto SYN il primo dei tre, con SYN/ACK il secondo e
con ACK il terzo.
Gestione Sequence number e Acknowledgement
number in una connessione
Il TCP realizza una connessione affidabile, è in grado
cioè, di recuperare pacchetti persi, duplicati e fuori ordine.
Tutto questo è possibile grazie all'assegnamento di un numero di
sequenza (sequence number) ad ogni byte trasmesso e alla
richiesta di conferma dei dati ricevuti dal destinatario
(acknowledgement number). All'interno di un pacchetto il
sequence number indica il numero di sequenza del primo byte di
dati contenuto, mentre l'Acknowledgement number indica il
numero del prossimo byte atteso e conferma la ricezione fino al
byte indicato meno 1.
Prendiamo in esame il seguente esempio per capire
meglio.
SEQ-NUM=1000 ACK-NUM=5000 DATI=100 byte
1) A -----------------------------------------> B
SEQ-NUM=5000 ACK-NUM=1100 DATI=250 byte
2) A <----------------------------------------- B
SEQ-NUM=1100 ACK-NUM=5250 DATI=150 byte
3) A -----------------------------------------> B
SEQ-NUM=5250 ACK-NUM=1250 DATI=0 byte
4) A <----------------------------------------- B
14
Il presente
Nel caso 1) A spedisce a B 100 byte il cui primo byte ha
come numero di sequenza 1000. Inoltre conferma la ricezione
dei byte ricevuti in precedenza fino al 4999 ed indica che si
aspetta che il prossimo byte trasmesso sia quello con numero di
sequenza 5000.
Nel caso 2) B spedisce ad A 250 byte il cui primo byte ha
come numero di sequenza 5000. Inoltre conferma la ricezione
dei byte ricevuti in precedenza fino al 1099 ed indica che si
aspetta che il prossimo byte trasmesso sia quello con numero di
sequenza 1100.
Nel caso 3) A spedisce a B 150 byte il cui primo byte ha
come numero di sequenza 1100. Inoltre conferma la ricezione
dei byte ricevuti in precedenza fino al 5249 ed indica che si
aspetta che il prossimo byte trasmesso sia quello con numero di
sequenza 5250.
Nel caso 4) B non ha dati da spedire, si limita solo a
confermare i dati ricevuti. Questo pacchetto non verrà
confermato in quanto non contiene dati.
Chiusura di una connessione
Sebbene le connessioni TCP siano full duplex, per
comprendere la chiusura di una connessione è meglio pensarle
come una coppia di connessioni simplex.
Ogni connessione simplex viene chiusa
indipendentemente dall'altra. Per chiudere una connessione
entrambe le parti possono spedire un pacchetto TCP contenente
il flag FIN impostato a uno per indicare che non ci sono più
dati da spedire. Quando viene confermata la ricezione del flag
FIN quella connessione viene spenta. Quando entrambe le
direzioni vengono chiuse la connessione viene rilasciata. Quindi
normalmente occorrono 4 passaggi per chiudere una
connessione.
2.4
Le porte
Quando un host si collega ad un server, i due computer
trasmettono continuamente i propri dati attraverso delle porte.
Ogni porta ha un numero associato e compie un servizio
specifico.
Il servizio è compiuto da un programma, chiamato demone
che esegue i comandi necessari per compiere il servizio
richiesto.
Le porte sono suddivise in 2 categorie :
• Da 0 a 255
• Da 255 a 65535
Le prime sono dette well – known port poiché i loro
servizi sono noti e precisati, mentre le altre porte non hanno
tutte un servizio preciso e in alcuni casi sono addirittura dei
doppioni delle porte conosciute.
15
Il presente
Ad esempio la porta 80 svolge il servizio http, ma anche la
porta 8080 svolge la stessa occupazione.
Quando ci si collega ad una rete tra cui anche Internet,
come detto in precedenza, due terminali si scambiano
informazioni attraverso le porte, ma non tutte vengono usate
nello stesso collegamento.
Esse si possono trovare in 4 stati:
• Ascolto
• Comunicazione
• Chiusura
• Attesa
Quando una porta è chiusa, per un hacker è impossibile
tentare di entrarci, quindi ogni tentativo di intrusione fallirà.
2.4.1
E s e m p i di porte
Legenda
Porta
C/S
Poss. att.
Note
: indica la porta utilizzata
: se il servizio descritto è dalla parte del
server (S), oppure dal lato client (C).
: indica le possibilità di attacco alla porta.
: varie ed eventuali, come ad esempio
possibilità di attacco ai servizi presenti su
quella porta, presenza di back door, ecc…
PORTA
C/S
POSS. ATT.
NOTE
ICMP (0)
//
Sezione relativa alla manutenzione del
protocollo TCP/IP
FTP (21)
S
Ricezione di
pacchetti anomali
per mandare in crash
lo stack TCP/IP
//
Telnet (23)
S
//
//
SMTP (25)
S
//
DNS (53)
S
Bug di Sendmail
(UNIX)
//
TFTP (69)
S
//
//
Finger (79)
S
Disabilitare il Finger o montare una
versione aggiornata
WEB (80)
S
Può essere usato per
un “denial of
service” attack
CGI/BIN attacks
POP3 (110)
S
TCP (119)
S
Possibile lettura file
in posta
//
NetBios
(137)
Proxy
(1080)
S
//
C/S
//
//
//
Utilizzare sempre la versione aggiornata
del server WEB
//
//
E’ necessario disattivare NetBios. Oppure
installare WinNuke95
Chi cerca una connessione sulla 1080
vuole mandare in giro pacchetti a nome
vostro, alcuni ISP mettono a disposizione
un server proxy per velocizzare le
16
Il presente
5001
C/S
//
IRC (6667)
S
//
12345 /
12346
C/S
//
UDP
(31337)
C/S
//
2.5
comunicazioni. L’effetto collaterale è che
tutti i pacchetti in uscita hanno
l’indirizzo IP del proxy server.
Porta destinazione degli attacchi di
Socket de Trois
//
Porte del server NetBus, si possono
ricevere scan alla ricerca di un dato
programma
E’ la porta standard del server di Back
Orifice
I socket
I socket sono i principali oggetti utilizzati dalle
applicazioni per eseguire la maggior parte delle comunicazioni di
rete. Sono stati inizialmente utilizzati per UNIX alla Università
di California di Berkeley e sono stati progettati in modo che le
comunicazioni di rete fra applicazioni potessero avvenire nello
stesso modo in cui quelle stesse applicazioni leggevano e
scrivevano i file. Da allora vi è stato un progresso anche per
quanto riguarda i socket ma il funzionamento di base è rimasto
immutato.
La creazione di una connessione via socket richiede due
informazioni principali :
• bisogna sapere il nome del server;
• bisogna conoscere la porta su cui il server è in
ascolto.
Esempio
85.125.255.12 : 80
Indirizzo IP
Porta
È possibile riassumere i socket come l’unione
dell’indirizzo IP più la porta.
È importante dire che solo un’applicazione può essere in
ascolto in una determinata porta e su un determinato computer.
Anche se su un computer vi possono essere più applicazioni che
ascoltano più richieste di connessione su un singolo computer,
ognuna di esse deve essere in ascolto su una porta differente.
2.6
Esempi
Il sistema operativo MS – DOS mette a disposizione due
programmi, Netstat e Tracert. Ambedue i programmi servono
per controllare parametri relativi alle connessioni, quali le porte
e i pacchetti TCP/IP.
17
Il presente
2.6.1
Netsat
La funzione Netstat permette di vedere tutte le porte
aperte del proprio host durante una connessione TCP/IP. Esso,
per ogni porta locale, specifica a quale indirizzo remoto è
connessa e quale porta il remoto sta utilizzando, inoltre
specifica per ogni connessione il protocollo (TCP, UDP) e lo
stato della porta.
Sintassi
Protocollo
2.6.2
netstat –sn
Indirizzo host
Indirizzo server
Stato socket
Tracert
La funzione Tracert permette, specificando un sito, di
tenere traccia del percorso che il pacchetto compie per arrivare
dal provider al server in cui è ospitato il sito.
Sintassi
Numero passaggi
tracert (nome sito)
Tempo passato
nel nodo
Indirizzo del sito
18
La crittografia
Capitolo 3
La crittografia
3.1
3.2
3.3
3.4
3.5
3.6
3.7
3.1
La storia
3.1.1
Crittografia antica
3.1.2
Crittografia fino al XVIII secolo
3.1.3
Crittografia moderna
Principali cifrari
3.2.1
Cifrari a sostituzione
3.2.2
Cifrario affine
3.2.3
Cifrario Playfair
3.2.4
Stream cypher
3.2.5
Cifrario di Vernam
La sicurezza perfetta
Gli algoritmi
3.4.1
Il DES
3.4.2
L’ RSA
Macchine cifranti
3.5.1
Enigma
3.5.2
La bomba di Turing
Crittoanalisi
3.6.1
Crittoanalisi statistica
3.6.2
Crittoanalisi lineare
3.6.3
Crittoanalisi differenziale
3.6.4
Crittoanalisi su polialfabetici
3.6.5
Brute force
Curiosità e considerazioni
La storia
Per migliaia di anni re, regine e generali hanno avuto il
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 mano
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, tecniche di alterazione del messaggio
destinate a renderlo comprensibile solo alle persone
autorizzate.
Una delle prime tecniche di comunicazione segrete, basata
sull'occultamento del messaggio, si chiama steganografia, dalle
parole greche steganós, che significa coperto, e gráphein, che
significa scrivere. Negli anni sono state impiegate in tutto il
mondo innumerevoli forme di steganografia.
Uno dei metodi più bizzarri per trasmettere le
informazioni segrete era utilizzato nell'antica Persia e viene
19
La crittografia
raccontato da Erodoto. Esso consisteva nel rapare i capelli di
uno schiavo e nel scrivergli il messaggio sulla testa. Lo schiavo
si recava poi dal destinatario del messaggio dopo che gli erano
ricresciuti i capelli e il messaggio era recuperato rapandoglieli
nuovamente.
Nell'antica Cina si dipingeva il messaggio su striscioline di
seta finissima, che venivano appallottolate e coperte di cera. Le
palline erano quindi inghiottite dal messaggero. Nel XVI secolo
lo scienziato italiano Giambattista Della Porta spiegò come
comunicare tramite un uovo sodo, preparando un inchiostro con
30 grammi di allume in mezzo litro d'aceto, e usandolo per
scrivere sul guscio. La soluzione penetra nel guscio, che è
poroso, senza lasciar traccia, e tinge l'albume solidificato;
quest'ultimo potrà essere letto sbucciando l'uovo.
La longevità della steganografia dimostra che essa
garantisce una certa sicurezza, ma il suo punto debole è evidente
: se il latore del messaggio è attentamente perquisito, è
probabile che il messaggio sia scoperto; in tal caso, il nemico
può farne l'uso che crede. In altre parole, la segretezza è
perduta nel momento stesso dell'intercettazione. In tal caso è
inevitabile che molti messaggi siano trovati.
Perciò in parallelo con lo sviluppo della steganografia si
assisté all'evoluzione della crittografia, dal greco kryptós, che
significa nascosto. La crittografia non mira a nascondere il
messaggio in sé, ma il suo significato. Per rendere
incomprensibile un testo, lo si altera per mezzo di un
procedimento concordato a suo tempo dal mittente e dal
destinatario. Questi può quindi invertire il procedimento, e
ricavare il messaggio originale. Il vantaggio della crittografia è
che anche se il nemico intercetta il messaggio, esso risulta
incomprensibile e quindi inutilizzabile. Infatti il nemico, non
conoscendo il procedimento di alterazione, dovrebbe trovare
difficile, se non impossibile, ricostruire il significato.
Non tutte le società antiche svilupparono forme di
crittografia. La Cina, per esempio, l'unica civiltà antica ad usare
una scrittura ideografica, non ne ha mai viste. Le ragioni, a
detta degli storici, sono legate alla natura prevalentemente orale
delle comunicazioni.
In India, invece, forme di crittografia furono
concretamente praticate. In diversi testi sacri sono presenti
riferimenti a forme di scritture segrete. Nell'Artha-Sastra, un
testo classico sugli affari di stato, si sottolinea l'importanza
delle scritture segrete nei servizi di spionaggio. Esempi di
scritture segrete sono presenti anche nel Latila-Vistara, un
libro che esalta le virtù di Budda.
Anche nelle scritture cuneiforme sviluppate in
Mesopotamia sono stati ritrovati esempi di crittografia. Sia
presso gli Assiri che i Babilonesi, le due grosse civiltà sorte
sulle sponde del Tigri, è stata rinvenuta l'usanza di sostituire le
parti terminali delle parole con elementi corti e stereotipati detti
colofoni. In Iraq, nel periodo finale delle scritture cuneiformi, è
presente per la prima volta la sostituzione di nomi con numeri.
20
La crittografia
Anche se la steganografia e la crittografia sono discipline
indipendenti, possono essere impiegate per alterare e occultare
il medesimo testo, garantendo un livello di sicurezza molto più
alto. Per esempio, il « microdot », cioè la riduzione di uno scritto
alle dimensioni di un punto, è una forma di steganografia che
ebbe largo impiego durante la seconda guerra mondiale. Tramite
un procedimento fotografico, gli agenti tedeschi in America
latina trasformavano una pagina scritta, precedentemente
crittografata, in una macchia con un diametro inferiore al
millimetro, che poteva essere nascosta nel puntino di una « i » in
una comunicazione banale. Il primo microdot fu scoperto dall'
FBI nel 1941 grazie a una soffiata.
3.1.1
Crittografia antica
Le più antiche notizie sicure sono probabilmente
quelle sulla scitala lacedemonica , data da Plutarco come
in uso dai tempi di Licurgo (IX sec a.C.) ma più
sicuramente usata ai tempi di Lisandro(verso il 400
a.C.). Consisteva in un bastone su cui si avvolgeva ad
elica un nastro di cuoio; sul nastro si scriveva per
colonne parallele all'asse del bastone, lettera per
lettera, il testo segreto. Tolto il nastro dal bastone, il
testo vi risultava trasposto in modo regolare ma
sufficiente per evitare la comprensione senza un
secondo bastone uguale al primo.
Figura 3.1 : Scitala lacedemonica
Tra il 390 e il 360 a.C. venne compilato da
Enea il tattico, generale della lega arcadica, il
primo trattato di cifrari il cui XXI capitolo tratta
appunto di messaggi segreti. In questo viene
descritto un disco sulla zona esterna del quale
erano contenuti 24 fori, ciascuno dei quali era
contrassegnato da una lettera disposte in ordine
alfabetico. Un filo, partendo da un foro centrale,
Figura 3.2 : Disco di Enea
si avvolgeva passando per i fori delle successive
lettere del testo. Il destinatario del messaggio svolgeva il filo
dal disco segnando le lettere da esso indicate. Il testo si doveva
poi leggere a rovescio.
Nei testi sacri, in particolare nel Vecchio Testamento, si
possono ritrovare tre principali scritture segrete : l’ Atbash, l’
Albam e l’ Atbah. Il primo codice cifrato, l’ Atbash, è stato
ideato dal popolo ebraico. Esso consisteva nel capovolgere
l’alfabeto, di conseguenza la prima lettera diventava l’ultima e
l’ultima la prima e così per tutte le altre lettere dell’alfabeto.
Usando l’ attuale alfabeto ordinario, l’ Atbash può essere
riassunto con la seguente tabella di cifratura :
21
La crittografia
L'Albam richiede che l'alfabeto venga diviso in due parti e
che ogni lettera venga sostituita con la corrispondente dell'altra
metà. Infine, l'Atbah, richiede che la sostituzione soddisfi una
relazione di tipo numerico. Le prime nove lettere dell'alfabeto
vengono sostituite in modo tale che la somma della lettera da
sostituire e della lettera sostituente risulti uguale a dieci. Per le
restanti lettere dell'alfabeto deve valere una regola simile con
somma pari a 28 in decimale.
a b c d e f g h i j k l mn o p q r s t u v w x y z
z y x w v u t s r q p o n ml k j i h g f e d c b a
Lo storico greco Polibio (200 ca. -118 a.C.), nelle sue
Storie (Libro X) descrive un interessante metodo di cifratura.
L'idea è quella di cifrare una lettera con una coppia di numeri
compresi tra 1 e 5, in base ad una matrice 5x5, contenente le
lettere dell'alfabeto. Ogni lettera viene rappresentata da due
numeri, guardando la riga e la colonna in cui essa si trova. Per
esempio, a=11 e r=42.Inoltre, Polibio, suggeriva di mandare
tanti messaggeri quanti erano i caratteri del messaggio. Questi
portavano nella mano sinistra un numero di torce pari all'indice
di riga e nella mano destra un numero pari all'indice di colonna.
In effetti più che di un codice segreto, si tratta di un sistema di
telecomunicazione, di fatto un telegrafo ottico. Telegrafi a torce
esistevano da molti secoli ed erano stati descritti da Enea il
tattico intorno al 350 a.C., ma erano basati su un limitato elenco
di messaggi possibili; quello di Polibio si basa invece sulla
scomposizione del messaggio nelle singole lettere ed è quindi in
grado di trasmettere qualsiasi messaggio.
#
1
2
3
4
5
1
A
F
KQ
P
V
2
B
G
L
R
W
3
C
H
M
S
X
4
D
I
N
T
Y
5
E
J
O
U
Z
Svetonio nella Vita dei dodici Cesari, un'opera del II secolo
d.C., racconta che Giulio Cesare usava per le sue corrispondenze
riservate un codice di sostituzione molto semplice, nel quale
ogni lettera del testo veniva sostituita dalla lettera che la segue
di tre posti nell'alfabeto ( Restano quelle a Cicerone,così come quelle
ai familiari sugli affari domestici, nelle quali, se doveva fare delle
comunicazioni segrete, le scriveva in codice, cioè con l'ordine delle lettere
così disposto che nessuna parola potesse essere ricostruita: se qualcuno
avesse voluto capire il senso e decifrare, avrebbe dovuto cambiare la
quarta lettera degli elementi, cioè D per A e così via per le rimanenti. ).
a b c d e f g h i j k l mn o p q r s t u v w x y z
d e f g h i j k l mn o p q r s t u v w x y z a b c
22
La crittografia
Ad esempio la lettera A è sostituita dalla D, la B dalla E e
così via fino alle ultime lettere che sono cifrate con le prime
come nella tabella che segue (che fa riferimento all'odierno
alfabeto internazionale).
3.1.2
La crittografia fino al XVIII secolo
Un sistema usato dall'Arcivescovo di Napoli, Pietro di
Grazia, tra il 1363 e il 1365, é quello in cui le lettere sono
cifrate con numeri o simboli speciali. La corrispondenza tra
lettere e simboli o numeri per la sostituzione è fissata da una
tabella. Dagli inizi del XIV secolo, per depistare i tentativi di
analisi statistica delle frequenze, si iniziano ad usare più segni
per cifrare le vocali, dato che queste sono molto ricorrenti in un
testo. Successivamente tale tecnica viene estesa anche alle
consonanti più ricorrenti. Inoltre alcune parole, utilizzate
frequentemente, (Papa, et, con, quo, etc.) sono sostituite con un
solo simbolo. Un primo esempio di questa cifratura fu la lettera
di Michele Steno scritta nel 1411.
Figura 3.3 : Lettera di
Michele Steno
Leon Battista Alberti, nel suo Trattato, ha proposto un
disco composto di due cerchi concentrici di rame. Uno esterno
fisso di diametro maggiore sul quale sono riportate le lettere
dell'alfabeto in chiaro e uno interno mobile per le lettere
dell'alfabeto cifrante. Il disco esterno è composto di 24 caselle
contenenti 20 lettere maiuscole in ordine lessicografico, escluse
H, J, K, W, Y, al posto delle quali ci sono i numeri 1, 2, 3, 4.
Il disco interno riporta le 24 lettere minuscole in maniera
disordinata (la u e la v sono collassate) ed un simbolo speciale
&.
23
La crittografia
Fissata una lettera maiuscola come chiave, ad esempio B,
si deve spostare il disco mobile interno in modo da far
corrispondere la B con un simbolo particolare del disco
interno(&). Si stabilisce in tal modo un'associazione tra le
lettere dell'alfabeto in chiaro e quello dell'alfabeto cifrante.
Può anche essere
utilizzata una chiave diversa
per ogni parola del testo in
chiaro. Le lettere che di volta
in volta corrispondono ai
numeri 1 2 3 4 non vengono
usate per la cifratura. Tutte le
lettere del messaggio da
cifrare sono cambiate in base
all'associazione tra le lettere
maiuscole e quelle minuscole.
Tale disco non ottenne
Figura 3.4 : Disco
successo anche per la
d e c i s i o n e d e l l ' A l b e r t i d i dell’Alberti
tenerlo segreto (il suo trattato fu pubblicato solo un secolo più
tardi a Venezia insieme ad altri suoi "opuscoli morali" e passò
quasi inosservato).
Il bresciano Giovan Battista Bellaso pubblicò tra il 1553 e il
1564 tre opere di crittologia contenenti alcuni cifrari polialfabetici
di notevole interesse.
L'idea su cui si basa il principale cifrario proposto dal
Bellaso è quella di ricavare cinque alfabeti da una parola segreta
convenuta. Le lettere dell' alfabeto vengono scritte in una
tabella composta da due righe. In particolare quelle della parola
segreta sono inserite nelle prime colonne intercalate sulle due
righe e le rimanenti lettere dell'alfabeto vengono scritte di
seguito. In questo modo si è ottenuto il primo alfabeto derivato.
A partire da questo ricaviamo il secondo spostando
circolarmente verso destra la seconda riga di una posizione.
Applicando lo stesso procedimento al secondo alfabeto, si ricava
il terzo alfabeto derivato e così via fino ad ottenerne cinque,
ognuno dei quali sarà identificato da un gruppo di quattro
lettere. Facendo riferimento sempre al primo alfabeto, le lettere
della prima e della sesta colonna identificano il primo alfabeto
derivato, quelle della seconda e della settima colonna
identificano il secondo alfabeto derivato. In generale le quattro
lettere che identificano l' i-esimo alfabeto sono quelle dell' iesima e della (i + 5)-esima colonna. A questo punto si deve
convenire una frase segreta; le lettere di quest’ ultima servono a
selezionare l' alfabeto da usare. In particolare, presa l' i-esima
lettera della parola segreta, si controlla quale dei cinque
identificativi degli alfabeti la contiene. Si determina così
l'alfabeto da usare per l' i-esima parola del testo in chiaro. Se il
numero di lettere della frase segreta è minore del numero di
parole del testo da cifrare, la frase segreta viene riapplicata
ciclicamente per la selezione degli alfabeti. La cifratura si
24
La crittografia
effettua sostituendo la lettera del testo in chiaro con la lettera
che si trova sulla stessa colonna nell'alfabeto predeterminato.
Blaise de Vigenére pubblicò nel 1586 un trattato di cifrari
nel quale proponeva tra gli altri un codice che ebbe grande
fortuna e che è ricordato con il suo nome. Si tratta del più
semplice codice di sostituzione polialfabetica, e proprio per la sua
semplicità ha goduto per secoli di una grossa fama.
La forza del cifrario di Vigenére sta nell'utilizzare non uno
ma 26 alfabeti cifranti per cifrare un solo messaggio. Il metodo
si può considerare una generalizzazione del codice di Cesare;
invece di spostare sempre dello stesso numero di posti la lettera
da cifrare, questa viene spostata di un numero di posti variabile,
determinato dalle lettere della parola chiave, da concordarsi tra
mittente e destinatario. La parola è detta chiave o verme, per il
motivo che, essendo in genere molto più corta del messaggio,
deve essere ripetuta molte volte. Di seguito viene riportata il
cifrario utilizzato nei codici di Vigénère.
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
D
3.1.3
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
D
E
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
D
E
F
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
D
E
F
G
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
D
E
F
G
H
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
D
E
F
G
H
I
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
D
E
F
G
H
I
J
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
D
E
F
G
H
I
J
K
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
D
E
F
G
H
I
J
K
L
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
D
E
F
G
H
I
J
K
L
M
O
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
P
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
Q
R
S
T
U
V
W
X
Y
Z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
R
S
T
U
V
W
X
Y
Z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
S
T
U
V
W
X
Y
Z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
T
U
V
W
X
Y
Z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
U
V
W
X
Y
Z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
V
W
X
Y
Z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
W
X
Y
Z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
X
Y
Z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
Y
Z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Z
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
La crittografia moderna
Il cifrario di Jefferson prende il nome dal suo inventore
Thomas Jefferson (1743-1826), uno degli autori della Dichiarazione
d'Indipendenza e Presidente degli USA nel 1801-1804. Jefferson
non lo mise mai in uso e il suo cifrario fu dimenticato fino al
1922, quando fu riscoperto e utilizzato, fino agli anni '50,
dall'esercito statunitense. E nel 1890 Etienne Bazeries un
25
La crittografia
crittologo francese propose l' "La
chiffre endecifrable", un cifrario del
tutto equivalente a quello di
Jefferson.
Il codice di Jefferson è un
metodo di cifratura meccanico
basato su un cilindro di circa 15
cm di lunghezza e 4 cm di
larghezza. Il cilindro è costituito
da 36 dischi, imperniati su di un
asse, in grado di ruotare
liberamente. Ogni disco riporta le
26 lettere dell'alfabeto sul bordo
esterno, in un ordine differente
Figura 3.5 : Cifrario di Jefferson
l'uno rispetto all' altro.
Inoltre i dischi possono volta per volta essere inseriti sull'asse
in un ordine differente per ogni cifratura, previo accordo tra
mittente e destinatario. La cifratura di un messaggio avviene nel
seguente modo : il messaggio viene prima di tutto diviso in
blocchi di 36 caratteri. Per ogni blocco, i dischi della macchina
vengono ruotati in modo tale da far comparire allineati su una
riga i caratteri del blocco. Una volta effettuata tale operazione,
si sceglie a caso un'altra riga, e si considera la corrispondente
sequenza di 36 lettere come il messaggio cifrato. Il ricevente,
che possiede un cilindro identico a quello del trasmittente, non
deve far altro che ruotare i dischi in modo tale da far comparire
il cifrato allineato su una riga. Compiuta questa operazione,
deve analizzare le restanti righe. Una sola di queste è una frase
di senso compiuto rappresentante il messaggio in chiaro. Una
variante è quella di fissare a priori la riga su cui sarà possibile
trovare il messaggio in chiaro.
Il cilindro di Jefferson è il primo esempio di una serie di
macchine cifranti basate su cilindri e dischi ruotanti intorno ad
un asse, la più celebre di tutte è la cosiddetta Macchina Enigma
usata dai Tedeschi nella Seconda Guerra Mondiale.
Il Playfair cipher fu inventato dal noto fisico Sir Charles
Wheatstone (1802-1875), ma il nome di Playfair deriva da colui
che ha divulgato nelle alte sfere governative questo metodo di
cifratura. Lyon Playfair, barone di St.Andrews, mostrò per la
prima volta questo sistema nel 1854 durante una cena
organizzata da Lord Granville alla presenza di Lord Palmerton
(1784-1865) allora ministro degli Esteri. La speranza di Playfair
era quella di far utilizzare il Cipher durante la guerra di Crimea
ma il sistema fu effettivamente utilizzato dall'esercito britannico
solamente a partire dalla guerra Boera. Il Cipher è ritenuto
essere il primo metodo di cifratura a bigrammi (coppie di
caratteri). Si usa una matrice di 25 lettere che viene riempita
nelle prime caselle con la parola chiave, abolendo le eventuali
lettere ripetute, ed è completata con le rimanenti lettere nel loro
ordine alfabetico. Si omette la W che, se necessario, potrà essere
cifrata come una doppia V.
26
La crittografia
Il testo in chiaro deve essere diviso in bigrammi di due
lettere consecutive. Le due lettere si cercano sul quadrato e si
sostituiscono con altre secondo le seguenti regole: se le due
lettere chiare si trovano su una stessa riga, si prendono le due
lettere che le seguono a destra; se una delle due lettere chiare si
trova sulla quinta colonna a destra, si prenderà la prima lettera a
sinistra della stessa riga. Se le due lettere chiare sono sulla
stessa colonna, si prendono le due lettere sottostanti; se una
lettera è nell'ultima riga, si prenderà la lettera che sta nella
prima riga della stessa colonna; se le due lettere sono in colonne
e righe diverse, si prendono le due che costituiscono un
rettangolo con esse, cominciando da quella che si trova nella
stessa riga della prima lettera del bigramma in chiaro; qualora il
bigramma chiaro presenti due lettere uguali si cercherà di
eliminare questo raddoppio, oppure di romperlo inserendo una
lettera rara (k, w, x, y).
Dopo che la Gran Bretagna dichiarò guerra alla Germania
il 3 settembre 1939, le operazioni di decifrazione Britanniche
furono spostate da Londra a Bletchley Park. Tra il 4 settembre
1939 e l'estate del 1944, Alan Turing (1912-1954) (uno dei più
famosi matematici di questo secolo, fra i fondatori
dell'informatica teorica) alloggiò al Crown Inn, a Shenley Brook
End, un villaggio vicino Bletchley. Il lavoro eseguito da Alan
Turing e dai suoi colleghi a Bletchley Park poté essere
completamente apprezzato solo molti anni dopo, quando cadde
il segreto militare sulle tecniche di crittoanalisi durante la
guerra. Quasi tutte le comunicazioni tedesche venivano cifrate
con una macchina chiamata Enigma. Questa macchina è una
nobile rappresentante dei cifrari a rotore, utilizzati fino
all'introduzione di cifrari elettronici e microelettronici che
hanno sconvolto e trasformato il mondo della crittografia. Per
"rompere" Enigma (alcuni dettagli della soluzione sono tenuti
segreti fino ad oggi) Turing, per conto del governo inglese, si
servì di gigantesche macchine chiamate appunto Colossi, che
possono considerarsi i precursori dei moderni calcolatori
elettronici. Turing è autore di ricerche estremamente importanti
sul concetto logico-matematico di calcolabilità : lo strumento
che egli ha proposto per affrontare il problema è noto oggi col
nome di macchina di Turing. Una delle prime macchine di
cifratura a rotori è stata costruita dal californiano Edward
Hebern, che la brevettò nel 1921. Autentici gioielli della
crittografia meccanica sono le macchine costruite da Boris
Hangelin; nel 1927 egli aveva rilevato una ditta che produceva
materiale crittografico e che ancora oggi è prospera e fiorente,
anche se ormai i rotori sono entrati nei musei della scienza. Per
rendersi conto di quanto i tempi siano cambiati basterà
ricordare che l' Enigma aveva un grande inconveniente: era
sprovvisto di stampante. I risultati apparivano illuminati su una
tastiera apposita, lettera dopo lettera, e una persona doveva
provvedere a trascriverli a mano su un foglio di carta. Una
27
La crittografia
stampante elettro-meccanica avrebbe appesantito troppo il
congegno e lo avrebbe reso poco maneggevole.
In un epoca di supercomputer e macchine potentissime il
codice Navajo è un monumento alla più potente e sofisticata
macchina che esista al mondo : la mente umana. Nel tentativo di
ottenere delle comunicazioni vocali "sicure" l'esercito USA,
prima della seconda guerra mondiale ha sperimentato l'uso della
lingua degli indiani Choctaws per criptare le comunicazioni
vocali, lingua che era già di per se "criptata". Dopo l'entrata in
guerra degli USA, nel 1941, lo studio di questo tipo di
"crittografia" venne esteso e si sperimentarono i linguaggi di
Commanches, Choctaws, Kiowas, Winnebagos, Seminoles,
Navajos, Hopis e Cherokees. Successivamente la Marina USA ha
proseguito il lavoro dell'esercito codificando, espandendo e
perfezionando il metodo, usando esclusivamente il linguaggio
Navajos. Usati con successo su molti fronti i "NAC" (Native
American Codetalkers) non hanno mai visto "infranto" il loro
"codice".
3.2
Principali cifrari
Di seguito verranno analizzati i principali cifrari utilizzati
nella storia.
3.2.1
Cifrari a sostituzione
In questi sistemi di cifratura, ogni simbolo del testo in
chiaro viene trasformato in un simbolo dell'alfabeto del testo
cifrato. I segni di punteggiatura e gli spazi non vengono cifrati,
in modo tale che il testo diventa un'unica stringa di caratteri
alfabetici. Questi cifrari si dividono in due categorie:
monoalfabetici e polialfabetici. Nei monoalfabetici, ogni carattere,
una volta sostituito con un altro carattere, conserverà tale
sostituzione durante tutta la fase di cifratura; per esempio, se la
parola “bacca” sarà cifrata in “efggf”, allora la lettera 'a' sarà
sempre cifrata con la 'f ', la 'c' con la 'g' e così via. Nei sistemi
polialfabetici, invece, lo stesso carattere può essere cifrato con
più caratteri. Un esempio di cifrario a sostituzione
monoalfabetica è quello di Cesare.
3.2.2
Cifrario affine
In questo cifrario la chiave é una coppia di interi in Z26
K = (a,b) con a,b ∈ Z26
Dato un messaggio x da cifrare, la funzione di cifratura é
del tipo
ek (x) = (ax + b) mod 26
28
La crittografia
Queste funzioni sono dette funzioni affini, da cui il nome
del cifrario.
Una funzione di cifratura deve essere iniettiva; se così non
fosse il ricevente non potrebbe decifrare il messaggio in modo
univoco. Pertanto la chiave (a, b) deve essere scelta in modo
che l'equazione
y = (ax + b) mod 26
abbia un'unica soluzione.
Supponendo di scegliere come chiave la coppia a = 2 e b =
0 e che il messaggio cifrato sia y = 0; allora la funzione di
cifratura sarà
ek (x) = 2x
e quindi per decifrare il messaggio l'equazione da risolvere
sarà
2x = 0 mod 26
Le soluzioni sono x = 0 e x = 13, quindi due messaggi in
chiaro distinti corrispondono allo stesso messaggio cifrato. Di
conseguenza la scelta a = 2 non è ammissibile perché si vuole
che la congruenza
ax = 0 mod 26
(1)
abbia un'unica soluzione per x. Sia d = gcd(a,26). Allora la
congruenza (1) ha almeno due distinte soluzioni in Z26, cioè x =
0 e x = 26/d. Per avere un'unica soluzione deve essere gcd(a,26)
= 1, cioè a deve essere primo con 26. Tale condizione è
necessaria e sufficiente affinché ek(x) risulti iniettiva.
Teorema
ax=y mod 26 ha un’unica soluzione per ogni y se e solo se gcd (a,
26) = 1.
Dimostrazione
Supponendo che ax = y mod 26 abbia un'unica soluzione
per ogni y e supponendo per assurdo che gcd(a, 26) = d >1.
Risolvendo l'equazione per y = 0 si giunge ad un assurdo; infatti
ax = 0 mod 26 ha due soluzioni distinte in Z26 : x = 0 e x =
26/d . Quindi è stato provato che esiste un y per cui ax = y mod
26 non ammette soluzione unica.
Sia gcd(a, 26) = 1, siano x1 e x2 soluzioni distinte di ax =
y mod 26 quindi
ax1 = ax2 mod 26
da cui
a(x1 - x2 ) = 0 mod 26
quindi
26 | a( x1 - x2 )
dato che gcd(a,26) = 1 si ha 26 | ( x1 - x2 ) quindi
x1 = x2 mod 26
così x1 e x2 sono la stessa soluzione.
Si calcoli la funzione di decifratura d applicata ad un
messaggio cifrato y. Siccome
y = ax + b mod 26
si ha che
y -b = ax mod 26
da cui
29
La crittografia
a-1 (y-b) mod 26 = x
quindi
d(y) = a-1 (y - b) mod 26.
Il numero di possibili chiavi per il cifrato affine è dato dal
numero di coppie (a,b), tali che b può assumere qualsiasi dei 26
possibili valori mentre a solo i valori tra 0 e 25 primi con 26.
Quindi il numero dei possibili valori che a può assumere è dato
dalla cardinalità di Z*26, che può essere determinata tramite la
funzione di Eulero:
f(26) = (13-1) (2-1) = 12
Pertanto il numero di possibili chiavi è 26x12 , troppo
basso per scoraggiare una ricerca esaustiva.
3.2.3
Cifrario Playfair
Questo sistema fa uso di una matrice 5 x 5, che
rappresenta la chiave, in cui ci sono 25 lettere distinte
dell'alfabeto disposte in ordine arbitrario. L'unica lettera non
presente è la Q, in quanto è la lettera che è quasi sempre seguita
dalla U e quindi facilmente riconoscibile. Ogni lettera individua
ed è individuata dal suo numero di riga e dal suo numero di
colonna. Il testo in chiaro deve essere di lunghezza pari, dovrà
essere diviso in coppie di caratteri e ciascuna coppia deve avere
caratteri distinti. Nel caso in cui il testo sia di lunghezza dispari
si aggiunge un carattere fittizio che non alteri il senso del
messaggio, per ottenere la parità. Analogo stratagemma si
utilizza se una delle coppie ha i due caratteri uguali: si inserisce
come secondo carattere uno che non altera la comprensione del
testo. Con queste caratteristiche ogni coppia di caratteri rientra
sicuramente in uno fra questi tre casi :
1. le due lettere della coppia si trovano sulla stessa
riga;
2. le due lettere si trovano sulla stessa colonna;
3. le due lettere non si trovano né sulla stessa riga né
sulla stessa colonna.
La cifratura è eseguita su una coppia di lettere per volta.
Ogni coppia del testo in chiaro rientra in uno dei tre casi
precedenti, ciascuno dei quali va trattato in modo differente:
1. le lettere della coppia del testo in chiaro vanno
cifrate con le lettere che le seguono sulla stessa riga
(con la convenzione “circolare” che l'ultima lettera
della riga sia seguita dalla prima). Per esempio per
la coppia WI si ha HS, WH diventa HI, ecc…;
2. le lettere della coppia del testo in chiaro vanno
cifrate con le lettere immediatamente sottostanti
30
La crittografia
(sempre con la convezione “circolare”) ; ad
esempio IG diventa BO e VB diventa IG;
3. in questo caso, che è il più frequente, le due lettere
individuano sulla matrice un “rettangolo” di cui due
vertici rappresentano la coppia di caratteri del
messaggio in chiaro e gli altri due i corrispondenti
caratteri del messaggio cifrato. La convezione che si
utilizza nella cifratura è che la prima lettera del
testo risultante é quella che si trova sulla stessa
riga della prima lettera della coppia in chiaro. Per
esempio, NC diventa PA, mentre CN diventa AP.
W
Y
E
M
T
3.2.4
H
A
F
N
U
I
B
G
O
V
S
C
J
P
X
K
D
L
R
Z
Stream cypher
Nei crittosistemi studiati fino ad ora successivi elementi
del testo in chiaro sono cifrati mediante la stessa chiave k, cioè
la stringa cifrata y è ottenuta nel modo seguente:
y = y1 y2 …. = ek (x1 ) ek (x2 ) ….
Crittosistemi di questo tipo sono spesso definiti “cifrari a
blocchi”. Un approccio alternativo consiste nell'utilizzare gli
“stream cipher”. L'idea di base consiste nel generare una
sequenza, detta “keystream”
z = z1 z2 .......
e nell'utilizzarla per cifrare la stringa
x = x1 x2 ……
del testo in chiaro nel modo seguente
ossia
dove
zi = fi ( k, x1 , …. , x i -1 )
L’elemento zi della sequenza è utilizzato per cifrare xi,
yi = ezi(xi)
Pertanto per cifrare la stringa x1 x2 ….. bisogna calcolare
z1, y1, z2, y2 …..
Analogamente per decifrare la stringa y1 y2 …..bisogna
calcolare
z1, x1, z2, x2 ......
Per esempio se P = C = K = Z26 le funzioni di cifratura e
decifratura possono essere le seguenti:
yi = xi + zi mod 26
xi = yi - zi mod 26
Gli stream cipher sono spesso definiti in termini binari,
cioè P = C = K = Z2. In tal caso le funzioni di cifratura e
decifratura possono essere le seguenti:
yi = xi + zi mod 2
31
La crittografia
xi = yi - zi mod 2
Se associamo a "0" il valore booleano "falso", ed a "1" il
valore booleano "vero" allora l'addizione modulo 2 corrisponde
allo XOR, pertanto la cifratura e la decifratura possono essere
implementate molto efficientemente in hardware.
Un metodo per generare la sequenza keystream a partire da
m valori k1 , . . . . , km consiste nel fissare i valori per z1, .….,
zm come z i = k i per ogni i = 1,……, m, e nel calcolare i valori
successivi in base ad una relazione di ricorrenza lineare di
grado m :
dove c0,….,cm-1 ∈ Z2 sono costanti predeterminate. Tale
ricorrenza è funzione lineare dei termini precedenti, ed ha grado
m perché ciascun termine dipende dagli m precedenti. In tal
caso la chiave consiste dei 2m valori ( k1……km ; c0 ......cm-1 ),
dove ki=zi per i = 1,….., m.
3.2.5
Cifrario di Vernam
Nel 1917 Gilbert Vernam, impiegato della compagnia
AT&T, inventò un ingegnosissimo sistema di protezione
crittografica, per comunicazioni su telegrafo, dei testi codificati
in binario. Egli costruì per prima cosa un dispositivo in grado di
leggere contemporaneamente due nastri in input e generare a
partire da essi un nastro di output tale che ciascun foro fosse
generato mediante uno XOR dei due corrispondenti fori sui
nastri input. Dopodiché prese un nastro su cui era perforata una
sequenza di caratteri casuale ed un nastro su cui era perforato
un testo reale e li passò nella sua macchina. Il risultato fu un
nastro completamente inintellegibile, ovvero cifrato.
Lo schema di crittografia di Vernam è uno schema onetime pad; un tale schema richiede che :
1. la chiave sia usata una sola volta (da qui il nome);
2. deve essere lunga almeno quanto il testo in chiaro;
3. fra i bit che compongono la chiave non deve esserci
alcuna relazione;
4. la chiave deve essere generata casualmente.
In pratica se il testo in chiaro è X = 0110 e la chiave è
K = 1100, applicando il metodo di Vernam si ottiene il seguente
testo cifrato :
Y= X ⊕ K = 1010
la decifratura si ottiene nel seguente modo:
X= Y ⊕ K = 0110
Notiamo che è stata applicata la stessa chiave ed è stata
effettuata la stessa operazione sia per la cifratura che per la
decifratura, ciò caratterizza un sistema crittografico reversibile,
questo è uno dei molti aspetti notevoli del cifrario di Vernam.
Per ciò che concerne la sicurezza, a tutt'oggi, questo è l'unico
32
La crittografia
metodo ad essere perfetto, ossia costituisce un cifrario
assolutamente indecifrabile in senso stretto.
Un cifrario si dice perfetto se, dati X il testo in chiaro e Y
il cifrato corrispondente, gode della seguente proprietà:
per ogni X’e Y’ risulta :
Pr ( X = X’ ) = Pr (X = X’ | Y = Y’ )
La proprietà di cui sopra si chiama sicurezza perfetta. Per
un cifrario che gode della sicurezza perfetta, l'indecisione nello
stabilire qual è il testo in chiaro X senza conoscere il testo
cifrato Y è la stessa che si ha su X conoscendo il testo cifrato
Y.
Le proprietà che caratterizzano l’one-time pad sono
estremamente restrittive, volendole rispettare si ottiene un
sistema scomodo da usare in pratica, considerando che le
ingombranti chiavi andrebbero generate in anticipo rispetto al
loro uso previsto, e conservate in luogo sicuro. Sono questi i
motivi per cui questo sistema non viene usato che per casi
eccezionali, come la famosa hot-line tra Washington e Mosca.
Un'altro problema è che l’one-time pad è modificabile; un
intruso può cambiare Y così che il messaggio M decifrato sia
differente dal messaggio spedito. Non ci sono modi per il
destinatario di controllare che il mittente abbia spedito proprio
il messaggio ricevuto. Ci sono delle varianti che possono evitare
di utilizzare delle chiavi così grandi, ma che fanno perdere la
perfezione al sistema perché introducono delle dipendenze
statistiche. Un esempio è quello di prendere una chiave in un
grosso testo, come la Bibbia, specificando un punto di inizio
qualunque, tutti i caratteri da quel punto in poi, formeranno la
chiave. La dipendenza statistica è insita proprio nel fatto che le
parole devono avere senso compiuto. La difficoltà per i
crittoanalisti, oltre alla conoscenza della chiave (punto di inizio
nel testo), sta anche nel capire qual è il testo utilizzato.
Il problema con le chiavi corte, che dunque devono essere
riutilizzate ciclicamente nel corso del messaggio, è che
producono, in uscita, delle regolarità statistiche che possono
essere usate dai crittoanalisti per forzare il cifrario.
3.3
Sicurezza perfetta
Ragionando con i moderni termini della teoria
dell'informazione, si comprende come la “somma” di una chiave
casuale ad un testo in chiaro annulli l'ordine intrinseco nel testo
stesso, producendo un cifrario a sua volta casuale, nel quale
l'entropia H, che rappresenta la quantità di informazione
contenuta in un messaggio X, è massima.
L'entropia H(X) di una variabile aleatoria X con
distribuzione di probabilità p1 , p2 , ……, pm , è uguale a
33
La crittografia
e definisce la quantità di informazione contenuta in X.
In termini di entropia è possibile definire un sistema di
cifratura come segue : sia X la variabile aleatoria associata al
messaggio in chiaro, sia Y la variabile aleatoria associata al
messaggio cifrato e sia K la variabile aleatoria associata alla
chiave, tutte con distribuzione di probabilità arbitraria. Con
questa definizione
Pr ( X = X’ ) = Pr (X = X’ | Y = Y’ )
si può scrivere
H ( X ) = H ( X | Y )
Affinché le tre variabili aleatorie X, Y, K realizzino un
sistema crittografico perfetto si deve avere :
• Cifratura : il testo cifrato è univocamente
determinato dal testo in chiaro e dalla chiave.
Formalmente : H ( Y | XK ) = 0
• Decifratura : il testo in chiaro è univocamente
determinato dal testo cifrato e dalla chiave.
Formalmente : H ( X | YK ) = 0
• Sicurezza perfetta : la conoscenza del testo
cifrato non dà alcuna informazione sul testo in
chiaro. Formalmente : H ( X | Y ) = H ( X )
Teorema
In un sistema crittografico con sicurezza perfetta, la lunghezza
della chiave deve essere tanto grande quanto quella del messaggio in
chiaro.
Dimostrazione
Supponendo che X sia il messaggio in chiaro,Y il
messaggio cifrato e che la chiave utilizzata sia K.
La mutua informazione I ( KX | Y ) può essere scritta
come
I ( KX | Y ) = H ( K | Y ) - H ( K | XY )
oppure come
I ( KX | Y ) = H ( X | Y ) - H ( X | YK )
da cui si ottiene
H ( K | Y ) = H ( K | XY ) + H ( X | Y ) - H ( X | YK ) (3)
dato che H ( X | YK ) = 0, si ottiene
H ( K | Y ) = H ( X | Y ) + H ( K | XY )
(4)
In più, dato che l'incertezza sulla chiave è più grande
dell'incertezza che si ha sulla chiave conoscendo anche il
messaggio cifrato Y, cioè H ( K ) ≥ H ( K | Y ), si può scrivere:
H ( K ) ≥ H ( K | Y )
= H ( X | Y ) + H ( K | XY )
per la (4)
= H ( X ) + H ( K | XY ) per la sicurezza perfetta
≥ H ( X )
siccome H ( K | XY ) ≥ 0
Ciò significa che l'incertezza che si ha sulla chiave è
maggiore o uguale della incertezza che si ha sul messaggio X. Se
supponiamo che X sia distribuito uniformemente, allora:
H ( X ) = log |X|
da cui la lunghezza di K è maggiore o uguale della
lunghezza di X, cioè
log |K| ≥ H ( K ) ≥ H ( X ) = log |X|.
34
La crittografia
3.4
Gli algoritmi
In questa sezione verranno esaminati due dei principali
algoritmi utilizzati per la cifratura di dati : il DES e l’ RSA.
Prima della trattazione tecnica verrà esaminata la storia dell’
algoritmo.
3.4.1
DES
Il DES (Data Encryption Standard) viene adottato dal
governo degli Stati Uniti nel 1977 come standard federale. Esso
deriva dall'algoritmo Lucifer inventato dall' IBM nei primi anni
'70. Mentre Lucifer era ancora in via di sviluppo il NBS
(National Bureau of Standard), diventato poi NIST (National
Institute of Standards and Technology) , sollecitò l'industria
americana alla creazione di un nuovo standard crittografico per
la protezione di dati riservati ma non classificati come "segreti
militari" o di "stato".
L'NBS non fu accontentato molto presto forse perché il governo
degli Stati Uniti non ha mai incoraggiato ricerche in questo
campo, comunque nel 1974 l'IBM propose un Lucifer modificato
a cui fu dato il nome di DEA (Data Encryption Algorithm). L’
NBS sceglie il DEA come standard ed è annunciato sul
documento N.46 di Federal Information, col nuovo e definitivo
nome di DES.
Tuttavia, se si riuscisse a far lavorare qualche migliaio di
computer del tipo PC simultaneamente, è possibile sperare di
scoprire la chiave in un periodo di tempo ragionevole.
Provando a fare un piccolo conto si ottiene che si hanno 256
possibili chiavi.
Supponendo che un PC calcoli un milione di chiavi al secondo,
occorreranno 256/106 = 72057594037,9 secondi, che sono
1200959900,63 minuti, che sono 20015998,3439 ore, che sono
833999,930995 giorni, che sono 2284,93 anni.
Quindi, per calcolare tutte le chiavi possibili bisognerà aspettare
circa 2285 anni !
Quindi, se si vuole essere sicuri di trovare la chiave in giornata,
sarà necessario calcolare quanti computer dovrebbero lavorare
simultaneamente. Cioè 2.285 x 365 = 834.025 macchine.
Riassumendo, bisogna far lavorare 834.025 computer
contemporaneamente per 24 ore per testare tutte le chiavi
possibili.
La chiave di crittografazione è lunga 64 bit, ma 8 bit sono
di controllo, quindi la chiave effettiva è di 56 bit. Questo porta
ad avere 256 (circa 72 milioni di miliardi) possibili chiavi in un
tentativo di attacco brute - force. In effetti un supercomputer
potrebbe scoprire la password in un tempo che va dalle 3 alle 10
ore (per quello che è noto a livello non militare).
35
La crittografia
Tuttavia, anche senza basarsi sull'attacco di forza bruta,
gli studiosi Biham e Shamir hanno ideato una nuova tecnica di
forzatura detta crittoanalisi differenziale. Questa tecnica
consiste nell'utilizzo dell'algoritmo per la cifratura di 247 testi
particolari ed il confronto dei risultati. Ancora in tempi più
recenti, Matsui ha ideato un altro tipo di forzatura a cui è stato
dato il nome di crittoanalisi lineare. Anche in questo caso
vengono cifrati dei testi noti, per la precisione 243, ed analizzati
i risultati con il testo da decifrare. I tempi di decrittazione sono
comunque lunghi: il primo esperimento di Matsui richiese 9735
postazioni di lavoro e 50 giorni e 12 ore di tempo.
Il DES non viene più certificato dal NIST. Ha tuttavia
ancora larghissimo impiego nelle trasmissione audiovisive (è
incluso nello standard IRDETO, usato nelle trasmissioni
svizzere) e nei sistemi di protezione di Bancomat e carte di
credito, data anche l'elevata velocità di crittografazione rispetto
al suo rivale RSA a chiave pubblica. Non può essere tuttavia
utilizzato in quei casi dove il valore dell'informazione da
proteggere superi certe cifre, dato che già tempo fa è stato
dimostrato che in circa 3 ore qualsiasi testo cifrato con DES
può essere riportato in chiaro tramite un computer dal costo di
1 milione di dollari.
E` comunque stata costruita una versione del DES,
chiamata Triplo DES, che utilizza 3 chiavi diverse ad ogni
passaggio di sovracifratura. Nonostante i risultati siano inferiori
alle aspettative, è stato innalzato moltissimo il tempo necessario
per un attacco di brute-force.
Manipolazione della chiave
Adesso verrà affrontato il primo stadio del cryptaggio che
consiste nel manipolare i bits della chiave.
Per prima cosa, bisogna sapere che la chiave si può presentare in
due forme diverse:
- una chiave a 56 bits come indicato precedentemente
- una chiave a 64 bits che non è altro che la stessa chiave
a cui è stata aggiunta una parità.
La parità
La parità è utilizzata durante le trasmissioni di dati binari al fine
di verificarne la corretta ricezione.
Essa consiste nell’aggiungere ad un "codice binario" un bit
supplementare per fare in modo
che il numero totale degli 1 sia sempre pari o dispari.
Si avranno, quindi, due tipi di parità, pari o dispari.
Esempio
10011000
10011001
parità dispari – abbiamo tre 1
parità pari – abbiamo quattro 1
36
La crittografia
Per lo stesso gruppo di dati (1001100), vengono applicati due
bits diversi per ottenere la parità desiderata.
Per il sistema DES, viene utilizzata la parità dispari.
Ora consideriamo un chiave a 56 bits:
12 34 56 3C F0 12 34
In binario avremo:
00010010001101000101011000111100111100000001001000110100
Applicando una parità dispari su ciascun gruppo di sette
bits si otterrà dunque:
00010011 13
00011010 1A
00010101 15
11000111 C7
Il numero "1" è sempre dispari.
11001110 CE
10000000 80
01001001 49
01101000 68
Quindi la chiave 12 34 56 3C F0 12 34 a 56 bits senza
parità corrisponde alla chiave
13 1A 15 C7 CE 80 49 68 a 64 bits con parità dispari.
Si potrà, quindi, determinare ciascuna delle due chiavi
possedendo l’altra.
Primo stadio
Prendiamo la chiave precedente a 64 bits.
13 1A 15 C7 CE 80 49 68
Verrà attribuito a ciascun bit una posizione da 1 a 64,
procedendo da sinistra verso destra.
1 2 3
0 0 0
17 18
0 0
33 34
1 1
49 50
0 1
4 5 6
1 0 0
19 20
0 1
35 36
0 0
51 52
0 0
7 8 9
1 1 0
21 22
0 1
37 38
1 1
53 54
1 0
10
0
23
0
39
1
55
0
11
0
24
1
40
0
56
1
12
1
25
1
41
1
57
0
13
1
26
1
42
0
58
1
14
0
27
0
43
0
59
1
15
1
28
0
44
0
60
0
16
0
29
0
45
0
61
1
30
1
46
0
62
0
31
1
47
0
63
0
32
1
48
0
64
0
Si cerca ora di ridurre questa chiave a 56 bits applicando
la seguente tabella di conversione:
57
01
10
19
63
07
14
21
49
58
02
11
55
62
06
13
41
50
59
03
47
54
61
05
33
42
51
60
39
46
53
28
25
34
43
52
31
38
45
20
17
26
35
44
23
30
37
12
09
18
27
36
15
22
29
04
Limitandosi a sostituire i valori indicati nella tabella con i
bit corrispondenti, si avrà:
37
La crittografia
0
0
0
0
0
1
0
0
0
1
0
0
0
0
0
1
1
1
1
0
0
0
1
0
1
0
0
0
1
0
1
0
1 0
1 1
0 0
0 0
1 0
1 1
0 1
1 1
0
0
0
0
1
1
0
1
C(0)
D(0)
I primi 28 bits compongono il gruppo C(0).
Gli ultimi 28 bits compongono il gruppo D(0) .
A questo punto occorre calcolare le sedici chiavi derivanti dalla
prima.
In effetti il sistema DES opera su sedici iterazioni e ciascuna di
loro a bisogno della propria chiave.
Il valore I corrisponde alle iterazioni e prenderà quindi i valori
1-16.
Inizio del ciclo
I = 1
Per ciascuno dei sedici valori di I , si effettueranno una o
due rotazioni circolari verso sinistra in funzione del valore
indicato nella seguente tabella:
Iterazione
Rotazione
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 1 2 2 2 2 2 2 1 2 2 2 2 2 2 1
In questo momento I=1. Dalla tabella si vede che occorre
effettuare una rotazione a sinistra.
La rotazione si farà su C(I-1) e su D(I-1) dunque per I=1 su
C(0) e su D(0).
Il risultato sarà C(I) e D(I) quindi C(1) e D(1).
C(0) =
MSB
LSB
0 0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
Il primo bit di sinistra scomparirà per passare a destra ed
il secondo bit a sinistra deve diventare il primo per cui si
ottiene:
MSB
LSB
0 1 1 1 0 0 0 1 1 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
C(1)
38
La crittografia
D(0) =
MSB
LSB
0 0 0 1 1 0 1 1 0 0 0 1 1 1 0 0 1 1 0 1 0 0 1 0 0 1 1 1
MSB
LSB
0 0 1 1 0 1 1 0 0 0 1 1 1 0 0 1 1 0 1 0 0 1 0 0 1 1 1 0
D(1)
A questo punto si opera su C(I) e su D(I) quindi C(1) e
D(1) .
Si comincerà con il riunire i due gruppi da 28 bits per formare
un nuovo gruppo da 56 bits. Ora verrà attribuito una riga a
ciascuno dei 56 bits e verrà applicata, infine, una permutazione
secondo la tavola definita più avanti.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
0 1 1 1 0 0 0 1 1 0 1 1 0 0
15 16 17 18 19 20 21 22 23 24 25 26 27 28
0 1 0 0 0 0 0 0 0 0 0 0 0 0
29 30 31 32 33 34 35 36 37 38 39 40 41 42
0 0 1 1 0 1 1 0 0 0 1 1 1 0
43 44 45 46 47 48 49 50 51 52 53 54 55 56
0 1 1 0 1 0 0 1 0 0 1 1 1 0
Tavola di permutazione
14 17 11 24 01 05
03 28 15 06 21 10
23 19 12 04 26 08
16 07 27 20 13 02
41 52 31 37 47 55
30 40 51 45 33 48
44 49 39 56 34 53
46 42 50 36 29 32
da cui otteniamo:
0
1
0
1
1
0
1
0
0
0
0
0
0
1
0
0
1
0
1
0
1
0
1
1
0
0
1
0
0
1
0
0
0
0
0
0
1
0
1
0
0
0
1
1
1
0
1
1
A questo punto si ha la chiave K(I) e dunque la chiave
K(1).
001000100000001101100001101011010100101011001001
La chiave è rappresentata sicuramente da 48 bits. Sarà lo stesso
per le sedici chiavi K(1)-K(16).
Di seguito, si passa a I=2 e si calcola la chiave K2.
39
La crittografia
Si calcoleranno così le sedici chiavi.
Il blocco dei dati
Ora che si hanno le sedici chiavi è possibile lavorare su
un blocco di dati di 64 bits così come è il cryptaggio.
Prendendo come esempio il seguente dato
45 45 15 35 50 11 05 23
in chiaro
In binario, si otterrà :
MSB
LSB
0100010101000101 0001010100110101 0101000000010001 0000010100100011
Allora si attribuirà, come fatto in precedenza, ciascun bit
ad una determinata riga (1-64) e verrà applicata una tavola di
permutazione a tutti i bits.
1 2 3
0 1 0
17 18
0 0
33 34
0 1
49 50
0 0
4 5 6
0 0 1
19 20
0 1
35 36
0 1
51 52
0 0
7 8 9
0 1 0
21 22
0 1
37 38
0 0
53 54
0 1
10
1
23
0
39
0
55
0
11
0
24
1
40
0
56
1
12
0
25
0
41
0
57
0
13
0
26
0
42
0
58
0
14
1
27
1
43
0
59
1
15
0
28
1
44
1
60
0
16
1
29
0
45
0
61
0
30
1
46
0
62
0
31
0
47
0
63
1
32
1
48
1
64
1
Tavola di permutazione iniziale (IP)
58 50 42 34 26 18 10 02
60 52 44 36 28 20 12 04
62 54 46 38 30 22 14 06
64 56 48 40 32 24 16 08
57 49 41 33 25 17 09 01
59 51 43 35 27 19 11 03
61 53 45 37 29 21 13 05
63 55 47 39 31 23 15 07
da cui otteniamo:
0
0
0
1
0
1
0
1
0
0
1
1
0
0
0
0
0
1
0
1
0
0
0
0
1
1
0
0
0
0
0
0
0
1
1
1
0
1
0
0
0
1
1
1
0
0
0
0
1
0
1
1
0
0
0
0
1
0 L(0)
1
1
0
0 R(0)
0
0
I primi 32 bits compongono L(0) gli ultimi 32 bits
compongono R(0).
A questo punto verrà applicato alle sedici chiavi.
40
La crittografia
Inizio del ciclo
I=1
Prendendo il blocco R(I-1) quindi R(0), si attribuirà
ciascun bit ad una riga determinata ed applichiamo la tabella
d’espansione che segue:
1 2 3 4 5 6
0 0 0 0 0 0
17 18 19 20 21
0 0 0 0 0
7
0
22
0
8 9 10 11
0 1 0 0
23 24 25 26
0 0 1 0
12 13 14 15 16
0 1 0 0 0
27 28 29 30 31 32
0 0 0 0 0 0
Tabella d’espansione
32 01 02 03 04 05
04 05 06 07 08 09
08 09 10 11 12 13
12 13 14 15 16 17
16 17 18 19 20 21
20 21 22 23 24 25
24 25 26 27 28 29
28 29 30 31 32 01
da cui otteniamo:
0
0
0
0
0
0
0
0
0
0
1
1
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
0 E(R(0))
0
1
0
0
Otterremo 48 bits poiché sono stai utilizzati più volte
alcuni bits.
Occorre quindi eseguire la seguente operazione:
E(R(I-1)) Xor K(I)
Per la prima iterazione si ottiene :
E(R(0)) Xor K(1)
Si dovrà quindi effettuare un’ operazione di XOR
esclusivo fra ciascun bit di E(R(0)) e ciascun bit della chiave K1
trovata precedentemente.
Si otterrà :
000000000001010001010000000000000001010000000000 E(R(0))
XOR
001000100000001101100001101011010100101011001001 K(1)
________________________________________________
001000100001011100110001101011010101111011001001
41
La crittografia
Separando i 48 bits ottenuti in otto gruppi di sei bits :
001000
100001
011100
110001
101011
010101
111011
001001
B(1)
B(2)
B(3)
B(4)
B(5)
B(6)
B(7)
B(8)
Otterremo otto valori B(1)-B(8) e ciascuno di essi sarà
associato ad una delle otto tavole che seguono (S-Box).
14 4 13 1 2 15 11
0 15 7 4 14 2 13
4 1 14 8 13 6 2
15 12 8 2 4 9 1
S1
8 3 10 6 12 5 9 0 7
1 10 6 12 11 9 5 3 8
11 15 12 9 7 3 10 5 0
7 5 11 3 14 10 0 6 13
S2
15 1 8 14 6 11 3 4 9
3 13 4 7 15 2 8 14 12
0 14 7 11 10 4 13 1 5
13 8 10 1 3 15 4 2 11
7 2 13 12 0 5 10
0 1 10 6 9 11 5
8 12 6 9 3 2 15
6 7 12 0 5 14 9
S3
10 0 9 14 6 3 15 5 1 13 12 7 11 4 2 8
13 7 0 9 3 4 6 10 2 8 5 14 12 11 15 1
13 6 4 9 8 15 3 0 11 1 2 12 5 10 14 7
1 10 13 0 6 9 8 7 4 15 14 3 11 5 2 12
7 13 14
13 8 11
10 6 9
3 15 0
S4
3 0 6 9 10 1
5 6 15 0 3 4
0 12 11 7 13 15
6 10 1 13 8 9
2 12 4 1 7 10 11
14 11 2 12 4 7 13
4 2 1 11 10 13 7
11 8 12 7 1 14 2
12 1 10 15
10 15 4 2
9 14 15 5
4 3 2 12
2
7
1
4
8 5 11 12 4 15
2 12 1 10 14 9
3 14 5 2 8 4
5 11 12 7 2 14
S5
6 8 5 3 15 13
1 5 0 15 10 3
8 15 9 12 5 6
13 6 15 0 9 10
S6
9 2 6 8 0 13 3 4
7 12 9 5 6 1 13 14
2 8 12 3 7 0 4 10
9 5 15 10 11 14 1 7
0 14 9
9 8 6
3 0 14
4 5 3
14 7 5 11
0 11 3 8
1 13 11 6
6 0 8 13
42
La crittografia
S7
4 11 2 14 15 0 8 13 3 12 9 7 5 10 6 1
13 0 11 7 4 9 1 10 14 3 5 12 2 15 8 6
1 4 11 13 12 3 7 14 10 15 6 8 0 5 9 2
6 11 13 8 1 4 10 7 9 5 0 15 14 2 3 12
S8
13 2 8 4 6 15 11 1 10 9 3 14 5 0 12 7
1 15 13 8 10 3 7 4 12 5 6 11 0 14 9 2
7 11 4 1 9 12 14 2 0 6 10 13 15 3 5 8
2 1 14 7 4 10 8 13 15 12 9 0 3 5 6 11
Prendiamo B(1) . Esso sarà associato alla tavola S1.
1 2 3 4 5 6
B(1)= 0 0 1 0 0 0
I bits 1 e 6 formeranno un codice di due bits che
chiameremo m.
m = 00 che corrisponde a 0 in decimale.
I bits 2-5 formeranno un codice di quattro bits che
chiameremo n.
n = 0100 che corrisponde a 4 in decimale.
Occorre a questo punto ritornare alla tavola S1 .
m indica il numero di linea della tavola, n indica il numero della
colonna.
Dunque bisognerà cercare il valore rappresentato nella linea 0,
colonna 4. Il valore trovato sarà 2, che in binario viene indicato
0010.
B(1) assume ora questo nuovo valore:
B(1)=0010
La stessa cosa viene fatta da B(2) a B(8) e troveremo i nuovi
valori:
B(2)=1101
B(3)=0010
B(4)=1001
B(5)=1110
B(6)=1101
B(7)=0010
B(8)=1010
Raggruppando da B(1) a B(8) , attribuiamo una riga a
ciascun bit e applichiamo la tabella che segue.
1 2 3 4 5
0 0 1 0 1
17 18 19 20
1 1 1 0
6
1
21
1
7
0
22
1
8 9 10 11 12 13 14 15 16
1 0 0 1 0 1 0 0 1
23 24 25 26 27 28 29 30 31 32
0 1 0 0 1 0 1 0 1 0
Tabella di permutazione p
16 07 20 21
29 12 28 17
43
La crittografia
01 15 23 26
05 18 31 10
02 08 24 14
32 27 03 09
19 13 30 06
22 11 04 25
da cui otteniamo:
1
1
0
1
0
0
1
1
0
0
0
1
1
1
1
1
0 1
0 1
0 0
1 0
1 0
1 0
0 1
0 0
A questo punto occorre applicare un XOR esclusivo fra i risultati ottenuti
ed i valori di L(I-1) per la prima iterazione L(0).
10011001000011100110011011011100
XOR
00010011001111000100111111101111 L(0)
________________________________
10001010001100100010100100110011 R(1)
L(I) = R(I-1)
per la prima iterazione L(1) = R(0)
Riassumendo:
L(1)=R(0)= 00000000100010000000000010000000
R(1)= 10001010001100100010100100110011
Adesso bisogna ritornare all’inizio del ciclo con I=2 per la
seconda iterazione. Per completare la cifratura occorrono sedici
iterazioni.
Fine
Appena applicata la sedicesima chiave, è necessario effettuare un’ultima
permutazione nel blocco R(16)-L(16). Questa volta, R(16) si trova davanti a L(16).
Verrà assegnato a ciascun bit del blocco il rispettivo posto ed applicata la
permutazione finale con l’aiuto della seguente tabella.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
1 1 0 0 0 0 0 0 1 1 0 1 1 0 1 0
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
0 0 0 1 1 1 1 1 0 1 0 1 1 1 0 1
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
1 1 1 1 1 0 1 0 1 0 1 1 0 1 1 1
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
1 0 1 1 1 0 0 1 0 1 0 0 1 0 0 0
44
La crittografia
Tabella di permutazione finale
40 08 48 16 56 24 64 32
39 07 47 15 55 23 63 31
38 06 46 14 54 22 62 30
37 05 45 13 53 21 61 29
36 04 44 12 52 20 60 28
35 03 43 11 51 19 59 27
34 02 42 10 50 18 58 26
33 01 41 09 49 17 57 25
Da cui si ottiene :
0 0 1 0 1 1 0 1
1 0 1 1 0 1 0 0
0 0 1 0 0 1 0 1
1 0 0 1 1 1 1 1
1 0 1 1 1 1 0 1
1 0 1 0 1 0 0 0
1 1 0 1 0 0 1 1
1 1 1 1 1 0 0 0
quindi
00101101 10110100 00100101 10011111 10111101 10101000
11010011 11111000
Convertendo questi valori in esadecimale si otterrà:
2D B4 25 9F BD A8 D3 F8
Che è quindi il valore cryptato di
45 45 15 35 50 11 05 23
con la chiave
13 1A 15 C7 CE 80 49 68
3.4.2
RSA
L’RSA è un algoritmo di codifica a chiave pubblica.
Questo algoritmo è a stato ideato da tre matematici Ron Rivest,
Adi Shamir e Leonard Adleman nel 1977. Questo algoritmo
sviluppa un codice cifrato attraverso un procedimento che
sfrutta le proprietà dei numeri primi.
L’RSA è formato da due chiavi, quella pubblica e quella
segreta. La chiave pubblica è calcolata facendo il prodotto tra
due fattori primi molto grandi, il risultato che troviamo N è un
numero che deve essere difficile da fattorizzare, questa N viene
resa pubblica.
Esempio
n = modulo
p = numero primo
q = numero primo
45
La crittografia
n = p * q = modulo
Si sceglie un numero ‘e’ primo rispetto a (p-1) (q-1), in
seguito si prende un numero ‘d’ tale che (e*d-1) sia divisibile
per (p-1) (q-1): il numero ‘e’ viene chiamato esponente
pubblico, il numero ‘d’ è l’esponente privato. Queste due chiavi
concorrono a formare la chiave pubblica, che è formata dalla
coppia (n,e), mentre la chiave privata è formata dai numeri
(n,d). Oggi è molto difficile fattorizzare ‘n’ nei due numeri ‘p’ e
‘q’ in tempi accettabili. Al momento non è possibile pensare ad
una forzatura dell’algoritmo RSA, poiché si utilizzano chiavi con
un numero di cifre superiore o uguale a duecento.
Figura 3.6 : Creazione
di una coppia di chiavi
con RSA
3.5
Macchine cifranti
In questa sezione verranno trattate le due macchine che si
sono rese protagoniste nella seconda guerra mondiale : Enigma e
la Bomba di Turing o Colossus.
3.5.1
Enigma
Nel 1918 l'inventore tedesco Arthur Scherbius avendo
studiato ingegneria elettrica ad Hannover e Monaco, mise a
punto un dispositivo crittografico che in sostanza era una
versione elettromeccanica del disco cifrante dell'Alberti.
46
La crittografia
La sua invenzione fu chiamata Enigma. Essa consiste di
diversi ingegnosi elementi combinati in un potente e sofisticato
dispositivo per la produzione di scritture segrete.
La versione semplificata del congegno di Scherbius
consiste in 3 componenti collegati da fili elettrici: una tastiera
per immettere le lettere del testo in chiaro; un'unità
scambiatrice che cifra la lettera trasformandola nel
corrispondente elemento del crittogramma (testo cifrato); un
visore con varie lampadine, che accendendosi indicano la lettera
da inserire nel testo cifrato.
Per generare il crittogramma, l'operatore preme il tasto
corrispondente alla lettera da cifrare; l'impulso elettrico
raggiunge l'unità scambiatrice, e dopo essere stato elaborato va
ad illuminare il visore in modo da evidenziare la lettera cifrata
corrispondente.
Figura 3.7 : Versione
semplificata della
macchina Enigma con
un alfabeto di sei
lettere.
Con questo schema di base lo scambiatore in sostanza
definisce una corrispondenza tra le lettere del testo in chiaro e
quelle cifrate, e la macchina può essere usata per realizzare una
semplice cifratura per sostituzione monoalfabetica. Il passo
successivo consiste nel far ruotare automaticamente il disco
scambiatore di un 1/26 di giro dopo la cifratura di ogni lettera.
In altre parole, la corrispondenza tra lettere in chiaro e cifrate
cambia dopo la cifratura di ogni lettera cosicché la cifratura di
una stessa lettera muta continuamente. Con questa disposizione
rotante, lo scambiatore in sostanza definisce 26 diverse
corrispondenze tra lettere in chiaro e cifrate, ed Enigma può
essere usata per effettuare una cifratura polialfabetica. Tuttavia,
così come è il congegno, ha un punto debole evidente; dopo 26
pressioni continue dello stesso 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. Per ridurre il
numero di ripetizioni può essere introdotto un altro
scambiatore. In questo modo, ogni volta che una lettera è
cifrata, il primo disco ruota di un carattere, mentre il secondo
disco invece resta immobile fin quando il primo scambiatore ha
completato un giro, solo a questo punto il secondo scambiatore
avanza di una posizione.
L'aggiunta del secondo scambiatore comporta il vantaggio
che lo schema della cifratura non si ripete finché il secondo
scambiatore non è tornato al punto di partenza, il che richiede
26 giri completi del primo scambiatore, ovvero la cifratura di
26x26=676 lettere. Per una sicurezza ancora maggiore viene
47
La crittografia
aggiunto un terzo rotore, per cui il numero di sostituzioni
diverse è 26x25x26=16.900 (il secondo rotore effettua una
rotazione in meno rispetto agli altri due, poiché dopo aver
effettuato un giro completo rimane fermo una volta per far
ruotare il terzo rotore). Inoltre viene aggiunto un riflessore
molto simile allo scambiatore che consiste in un disco di gomma
con circuiti interni che non ruotano e i fili entrano ed escono
dallo stesso lato. Col riflessore installato quando si digita una
lettera il segnale elettrico attraversa i 3 rotori, raggiunge il
riflessore ed è mandato indietro. Quindi il segnale elettrico
passa di nuovo nei rotori ma lungo un percorso diverso.
Figura 3.8 : Il progetto
di Scherbius del
modello base di Enigma
includeva un terzo
scambiatore e un
riflessore, che costringe
l'impulso elettrico ad
attraversare di nuovo gli
scambiatori.
Dato che il numero di chiavi è alto ma non abbastanza per
scoraggiare un crittoanalista che può disporre di più macchine e
più aiutanti, per accrescere l'affidabilità si dovrebbe aumentare
il numero di assetti cioè il numero di chiavi. Invece di
aggiungere un altro rotore e aumentare di 26 volte le chiavi sono
state introdotte due nuove caratteristiche. Innanzitutto si
possono utilizzare rotori removibili e sostituibili, ad esempio il
primo e il terzo rotore si possono scambiare di posto. Quindi
dati tre elementi intercambiabili essi possono essere permutati
in sei modi differenti; con questo accorgimento il numero di
chiavi aumenta di un fattore pari a sei. La seconda caratteristica
è l'inserimento di un pannello a prese multiple tra la tastiera e il
primo rotore. Il pannello permette al mittente di inserire alcuni
cavi muniti di spinotti, che aveva l'effetto di scambiare due
lettere prima della loro immissione nel rotore. L'operatore di
Enigma dispone di sei cavi che gli danno la possibilità di
scambiare sei coppie di lettere simultaneamente.
48
La crittografia
Figura 3.9 : Il pannello
a prese multiple è
interposto tra la tastiera
e gli scambiatori.
Inserendo gli appositi
cavetti è possibile
scambiare due lettere.
Calcolo del numero di chiavi possibili
Rotori
I due dischi rotanti più esterni effettuano 26 rotazioni
ognuno, mentre quello centrale ne effettua 25, quindi sono
ammesse 26x25x26=16.900 combinazioni di orientamenti.
Unità cifratrice
I tre rotori (1,2,e 3) possono essere inseriti nell'unità
centrale in diverse posizioni reciproche, così riassumibili: 123,
132, 213, 231, 312, 321. Sono quindi ammesse 6 diverse
posizioni reciproche dei rotori.
Pannello a prese multiple
I possibili abbinamenti di 2 x 6 = 12 lettere su 26 sono
moltissime, per l'esattezza 100.391.791.500, che si ottiene dalla
formula seguente dove p, il numero di cavi, è uguale a 6.
Il numero totale di chiavi si ottiene moltiplicando le
suddette possibilità: 16.900 x 6 x 100.391.791.500
49
La crittografia
Figura 3.10 : Pannello a prese multiple
Figura 3.11 : Disco rotante
50
La crittografia
Figura 3.12 : Macchina Enigma
Figura 3.13 : Scambiatore
51
La crittografia
3.5.2
La Bomba di Turing
Nel 1938 Dilly Knox era conoscenza del fatto che i rotori
usati dai tedeschi nella macchina Enigma fossero differenti da
quelli in commercio e, molto probabilmente, non sapeva neanche
il metodo di doppia cifratura del testo in chiaro, vero punto di
forza per i tedeschi.
In quel periodo, Alan Turing, tentò diverse vie per cercare
di forzare il sistema di cifratura dei tedeschi basandosi sulle
uniche informazioni in possesso dell’Inghilterra, ovvero un
“testo piano conosciuto” che in seguito verrà ribattezzato con il
nome di “crib”.
Turing pensò che se l’analisi dei testi cifrati poteva
portare a una parziale decrittazione dello stesso, l’utilizzo di
calcolatori, i quali potevano testare diverse configurazioni di
rotori in poco tempo, poteva portare a buoni risultati.
Inoltre, Turing, attraverso l’uso delle proprie abilità
matematiche, riuscì a dimostrare che una trasformazione da un
testo cifrato al testo in chiaro precludeva un vasto numero di
configurazioni di rotori.
La GC&CS (Governement Codes & Ciphers School), tra gli
anni tra il ’38 e il ’39, riuscì ad intercettare un gran numero di
testi cifrati con la relativa copia in chiaro, grazie anche alla
collaborazione di un impiegato polacco.
Tra le caratteristiche che Turing scovò occasionalmente vi
era quella che la stessa coppia chiaro/cifrato di caratteri
occorreva più volte in differenti punti del medesimo messaggio.
Questa caratteristica venne chiamata “clicks”.
.....JYCQRPWYDEMCJMRSR
.....SPRUCHNUMMERXEINS
.........|…|……....|.|….|...
Questo avveniva perché Enigma era reversibile, ovvero la
coppia chiaro/cifrato di R,C era la stessa C,R e M,E ed E,M.
L’occorrenza di una coppia è determinata dall’ordine del
rotore e dalla posizione iniziale di esso. Turing capì che,
l’ordine attuale dei rotori e la loro posizione di partenza,
potevano essere trovati provando tutte le configurazioni che
soddisfavano la coppia esaminata.
Ovviamente provare tutte le combinazioni possibili su una
sola macchina Enigma una alla volta avrebbe richiesto un tempo
impossibile. Di conseguenza, il passo seguente, fu quello di
considerare come il test poteva essere eseguito simultaneamente
per una particolare configurazione iniziale della macchina.
Il test di ogni coppia di lettere richiedeva un metodo per
determinare rapidamente quale configurazione fosse esatta o
errata. Questo faceva a capo al concetto di collegare insieme più
macchine Enigma per velocizzare le operazioni di decrittazione.
Il risultato fu quello di usare una macchina Enigma “aperta”.
52
La crittografia
A causa della configurazione elettrica di Enigma ciò non
era possibile perché gli ingressi e le uscite che conducevano
corrente erano fissati sul rotore, mentre nella configurazione
aperta studiata da Turing, il riflettore, che nella precedente
configurazione precludeva ogni possibilità di connessione, aveva
due lati. In particolare, quello di uscita era connesso a tre rotori
che rappresentavano i percorsi inversi effettuati dalla corrente
nella configurazione originale della macchina.
Questo metodo dava la possibilità di avere delle
connessioni in input/output separate, permettendo, così, di
avere più macchine Enigma in serie.
Figura 3.14 : Schema della macchina Enigma
modificata da Turing.
Nella Letchworth Enigma (chiamata così perché la fabbrica
British Tabulating Machine, che l’ha costruita, si trovava a
Letchworth) la cosa intelligente fu quella di includere ambedue i
cablaggi, anteriore e posteriore, dei rotori di Enigma in un unico
tamburo. Le connessioni tra un tamburo e il successivo
avvenivano tramite quattro cerchi composti da 26 contatti fissi
l’uno. I tre set di contatti erano cablati insieme,
permanentemente, ai connettori di input/output. I tre tamburi,
rappresentanti i tre rotori presenti sull’Enigma originale,
potevano essere posizionati sull’albero, formando una macchina
Enigma in configurazione aperta, con i connettori di
input/output separati dagli altri.
Ritornando al problema dei clicks, Turing decise di
affrontarlo nel seguente modo :
53
La crittografia
abcdefghijklmnopq
JYCQRPWYDEMCJMRSR
SPRUCHNUMMERXEINS
….|…|……....|.|……|...
pose un offset, rappresentato dall’alfabeto minuscolo, per
identificare ogni coppia. In questo modo C,R erano
rappresentate dall’offset c e e mentre M,E da j, k e n.
Alla connessione rappresentata dall’offset, in questo caso
la “C”, dell’Enigma a configurazione aperta veniva applicata una
tensione, in questo modo, le 26 lampadine attaccate ad essa
indicavano se la possibile cifratura era esatta. In questo caso si
sarebbe dovuta accendere la lampadina relativa alla lettera R.
Con una singola macchina Enigma questa operazione
avrebbe richiesto un incredibile numero di settaggi.
Figura 3.15 : Schema di risoluzione
del problema dei clicks.
Le macchine Enigma in configurazione aperta erano tutte
settate con lo stesso ordine di tamburi. Tutti i tamburi erano
settati nel medesimo modo, tranne l’ultimo che rappresentava
l’offset della lettera del crib da testare. In questo modo,
attraverso un set di relè era possibile fornire un voltaggio in
ingresso all’ultimo tamburo di tutte le macchine, così facendo
era possibile verificare se il settaggio dei tamburi soddisfava il
crib.
Se il risultato era negativo si procedeva a cambiare
l’ordine dei tamburi attraverso un motore elettrico.
Figura 3.16 : Schema
di settaggio dei
tamburi per la
risoluzione del
problema dei clicks.
54
La crittografia
Un estensione del concetto delle coppie di lettere è il loop
di lettere.
Abc def g hi j k lmnopq
JYCQRPRYDEMCJMRSR
SPRUCHNUMMERXEINS
.............|………….......||
Il primo problema fu quello di trovare le posizioni
principali S1, S2 e S3.
Figura 3.17 : Schema di risoluzione
del problema del loop.
Turing capì che c’era un’altra via per scoprire le
interconnessioni tra le macchine Enigma in configurazione
aperta.
Figura 3.18 : Schema
di settaggio dei
tamburi per la
risoluzione del
problema del loop..
Lo schema rappresenta tre macchine Enigma in
configurazione aperta. I tamburi numero 1 sono settati in
corrispondenza degli offset S1, S2 e S3. I tamburi numero 2 e 3
corrispondono alla configurazione standard dell’Enigma.
A questo punto le posizioni dei rotori corrisponderanno
alla posizione originale presente nella macchina Enigma al
momento della crittazione.
In questo modo il voltaggio di S1 sarà lo stesso in
ingresso di S2 mentre il voltaggio di S2 sarà l’ingresso di S3.
In questo modo si otterrà la configurazione originale.
55
La crittografia
Ora il trucco sta nel connettere i terminali di uscita
dall’ultima macchina nell’input della prima. Quest’ultima
operazione porterà ad avere un loop tra le macchine, isolando,
però, le connessioni S1, S2 e S3.
In seguito, Turing pensò che se S1 era sconosciuto e se gli
si applicasse un voltaggio casuale, questo raggiungerebbe tutte
le macchine ma non influenzerebbe gli ingressi S1, S2 e S3
perché essi non erano connessi a nessun terminale.
Il test finale consisteva nello spostare i rotori in modo da
vedere se una o 25 lampadine si accendevano. Se tutte le
lampadine erano accese la posizione era errata. Questo test
avveniva in pochissimo tempo, l’unico accorgimento era quello
di non surriscaldare i motori che muovevano i tamburi.
L’altra idea che ha permesso di perfezionare la Bomba di
Turing venne da Gordon Welchman. Egli pensò di costruire dei
registri, che opportunamente modificati potessero riassumere le
connessioni tra le macchine Enigma in configurazione aperta.
Attraverso la “Diagonal Board” (così fu chiamata) era facile
risalire alla corrispondenza tra le lettere, in particolare risultava
quasi immediata la soluzione nei casi di loop di cifre.
Figura 3.19 :
Diagonal Board.
Figura 3.20 : Vista
frontale della Bomba
di Turing.
56
La crittografia
Figura 3.21 : Vista
posteriore della
Bomba di Turing.
Figura 3.22 :
Manopola per il
settaggio dei tamburi.
3.6
Crittoanalisi
La crittoanalisi è la scienza parallela alla crittografia,
infatti essa è volta a debellare le protezioni offerte dalla
crittografia.
Di seguito verranno analizzate alcune delle tecniche usate
dai crittoanalisti per decifrare i più diffusi sistemi di
crittografia.
3.6.1
Crittoanalisi statistica
Uno dei sistemi più utilizzati per la crittoanalisi di testi
cifrati, specie quelli della famiglia dei metodi a sostituzione, è
proprio l'analisi della frequenza con cui si ripetono alcune
lettere in una data lingua.
Analizzando come esempio, un testo scritto in italiano,
anche di lunghezza limitata, si noterà sicuramente che le lettere
che compaiono con più frequenza, sono nell'ordine : e,i,a,o.
Questa caratteristica può essere sfruttata per decrittare cifrati
sconosciuti, o perlomeno come validissima informazione iniziale
per la crittoanalisi.
Analizzando un qualsiasi testo italiano, inglese, ecc. è
possibile stabilire per conto proprio quale sono le frequenze di
57
La crittografia
ogni lettera dell'alfabeto in tale lingua. Analizzando poi le
frequenze di un testo cifrato, si può capire con quale lettera è
stata sostituita, associando la frequenza di ogni singola lettera
del testo cifrato, con quella dell'alfabeto di tale lingua (che
andrà scoperta per tentativi se non conosciuta). Se ad esempio
in un testo che si sa essere italiano, spicca come lettera a
frequenza più alta la lettera "x", sicuramente tale lettera deve
essere sostituita con la lettera "e". Operando la sostituzione di
tutte le lettere del testo cifrato secondo questo schema, il testo
sarà decrittato come minimo al 60%. Ciò significa che ci si
troverà ad avere un testo con lettere mancanti o errate in ogni
parola, ma facilmente immaginabili.
Ovviamente con gli algoritmi polialfabetici, sebbene siano
metodi a sostituzione, le cose si complicano molto rispetto
all'analisi di un monoalfabetico creato, ad esempio, con il
cifrario di Cesare. Con i metodi monoalfabetici questo sistema
di crittoanalisi porta alla soluzione in un batter d'occhio (a
meno che non sia stato utilizzato anche un nomenclatore o un
dizionario), mentre con i polialfabetici si può operare solo a
blocchi di lunghezza pari alla chiave, dato che dopo tale
lunghezza l'alfabeto di sostituzione varia. In questi casi
conviene utilizzare la crittoanalisi lineare o differenziale.
3.6.2
Crittoanalisi lineare
La crittoanalisi lineare è un sistema di crittoanalisi basato
sull'analisi di una coppia cifrato - decifrato intercettata.
L'attacco ha lo scopo di scoprire la chiave utilizzata nei
messaggi. Non è necessario essere in possesso del programma
utilizzato per cifrare/decifrare.
Il metodo è orientato all'analisi tramite
un'approssimazione lineare volta a descrivere il comportamento
del blocco di bytes a partire dal testo in chiaro. Più in
particolare si lavora a livello di bit utilizzando un registro a
scorrimento per lo shift dei bytes ed effettuando la somma di
alcuni stadi con l'uscita di sinistra di tale registro. In base ai
dati così raccolti ed attentamente esaminati si può scoprire la
chiave. La probabilità di successo è alta.
Come funziona
Per prima cosa ai ha bisogno di un registro a scorrimento
lineare che sia composto di n elementi di memoria binaria, detti
stadi, il cui contenuto può essere la cifra 0 o la cifra 1; n è la
lunghezza del registro; l'ennupla binaria contenuta nel registro
in un dato momento è lo stato del registro in quel momento
(dunque gli stati possibili di un registro di lunghezza n sono 2n).
Ad intervalli di tempo regolari il contenuto di ciascuno stadio
viene trasferito (scorre) nello stadio di sinistra ed il contenuto
di S0 "esce" dal registro. Anche il contenuto dello stadio più a
58
La crittografia
sinistra, Sn-1, va aggiornato : ciò viene effettuato mediante la
funzione di retroazione, detta "feedback" del registro.
Tale funzione consiste in un addizionatore che è collegato
a certi stadi del registro : l'addizionatore somma il contenuto di
tali stadi (prima che il registro venga aggiornato) ed il risultato
viene appunto trasferito in Sn-1; la somma è quella binaria
modulo 2 in cui 1 + 1 = 0. Le uscite del registro sono costituite
dalle cifre binarie pseudocasuali che via via occupano lo stadio
S0.
Chiave pseudocasuale è sinonimo di chiave
"pseudoperfetta" (con riferimento al cifrario perfetto o di
Vernam) e potrebbe sembrare che un simile codice sia
inattaccabile ma non è così.
Si immagini che un crittanalista possa venire in possesso
della coppia messaggio - crittogramma; tale coppia può
effettivamente essergli sufficiente per capire qual è la chiave che
è stata usata, e dunque per decifrare tutti i crittogrammi futuri
che sarà in grado di intercettare : bastano 2n cifre di messaggio
e le 2n cifre del crittogramma corrispondente perchè il
crittanalista sia in grado di forzare il cifrario in maniera
completa.
Si supponga che il registro in questione abbia lunghezza 5,
e che il crittanalista abbia intercettato il messaggio m12 m13
m14...m20 m21, ed il crittogramma c12 c13 c14...c20 c21 (gli istanti di
tempo sono t=12, 13, 14,...20, 21). Poiché il crittogramma si
calcola sommando la chiave al messaggio cifra per cifra, si ha:
c12=m12+S0(12)
c13=m13+S0(13)...
c21=m21+S0(21)
Ciò consente al crittanalista di calcolare S0(12), S0(13),
...S0(21) :
S0(17)=a0S0(12)+a1S0(13)+a2S0(14)+a3S0(15)+a4S0(16)
S0(18)=a0S0(13)+a1S0(14)+a2S0(15)+a3S0(16)+a4S0(17)
S0(19)=a0S0(14)+...a4S0(18)
S0(20)=a0S0(15)+...a4S0(19)
S0(21)=a0S0(16)+...a4S0(20)
Queste 5 equazioni lineari consentono di trovare i valori
di a0, a1, a2, a3 e a4. Il crittanalista è ormai in grado di calcolare
anche S0(22), S0(23), e così via all'infinito : il cifrario è ormai
forzato.
Tale metodo fu per la prima volta usato da Matsui e
Yamagishi in un attacco al FEAL. Successivamente Matsui lo
estese e migliorò per forzare il DES, e da allora fu assai
studiato.
Langford e Hellman introdussero un attacco chiamato
crittanalisi lineare - differenziale, che combina elementi della
crittanalisi differenziale con quelli della lineare.
Nello stesso modo sono stati studiati metodi per
proteggere i testi cifrati da tali tipi di attacchi, e tra i maggiori
59
La crittografia
esponenti di tale ricerche, hanno voce in capitolo Nyberg,
Knudsen e O'Conner.
3.6.3
Crittoanalisi differenziale
La crittoanalisi differenziale è un tipo di attacco che può
essere adoperato per forzare dei blocchi di cifre iterativi.
Il metodo si basa sull'analisi delle differenze tra due testi
in chiaro cifrati con la stessa chiave.
L'utilizzo di questa tecnica, sebbene con un grande lavoro,
ha portato gli studiosi Biham e Shamir al successo nella
forzatura dell'algoritmo DES.
3.6.4
Crittoanalisi su polialfabetici
Il metodo crittografico cosiddetto "Le Chiffre
Indéciffrable" o meglio conosciuto con il nome di cifrario di
Vigénére è stato utilizzato molto a lungo perché ritenuto
inattaccabile (da cui il nome). In effetti è il precursore del
metodo più affidabile in assoluto, l’ one-time pad (o più
propriamente detto cifrario di Vernam), se non fosse che la
chiave di cifratura può essere anche cortissima e non casuale,
cosa che lo trasforma invece in un sistema attaccabile con i
metodi elaborati dal Kasiski.
abcdefghijklmnopqrstuvwxyz
Più in particolare, analizzando una cifratura come la
seguente con chiave "abc", si nota che:
Chiaro: Ciao a tutti
Chiave: abca b cabca
Cifr. : Dldo c wvvwj
La prima e la terza "t" della parola tutti è stata crittata
con la stessa lettera perchè? Perchè nel testo in chiaro, le due
"t" si sono trovate ad una distanza esatta alla lunghezza della
password. Pensate che un crittoanalista si lasci sfuggire un
simile indizio? Sicuramente no, anzi, prenderebbe tale evento e
lo confronterebbe con altri multipli o sottomultipli
L'attacco alla Kasiski si basa proprio sull'osservazione che
in un dato cifrato polialfabetico di questo tipo, si trovano
spesso questi duplicati di cifratura a distanze precise.
Individuando tutte le sequenze ripetute (e se ce ne sono
già in questa frase di 3 parole possiamo immaginare che in un
testo lungo ve ne saranno moltissime se la chiave è corta), il
massimo comune divisore tra le distanze delle ripetizioni è la
lunghezza della chiave o un suo multiplo. Trovata la lunghezza
della chiave, la decrittazione diventa semplice quanto un sistema
monoalfabetico.
60
La crittografia
3.6.5
Brute force
Il metodo di attacco Brute force (forza bruta), consiste
nell'effettuazione di una ricerca esaustiva della chiave di
decifrazione.
Questo tipo di attacco è possibile solo oggi, grazie ai
computer : sfruttando le loro caratteristiche di velocità
nell'effettuazione di operazioni quali la composizione di
stringhe alfanumeriche e la velocità di test dei risultati, è
possibile provare milioni di combinazioni in qualche minuto e
con macchine potenti ed ancora meglio con macchine
specializzate (la NSA stessa costruisce processori), anche in
frazioni di secondo.
Come si realizza
L'occorrente per un attacco di questo tipo, consiste in :
1. un programma che il destinatario deve usare per
decifrare (generalmente lo stesso programma
utilizzato dal mittente per cifrare);
2. un generatore di password;
3. un programma pilota del programma decifrante;
4. un programma di test con dizionario.
Il punto 1 è facile da realizzare : dall'estensione dei file o
da altre caratteristiche è facile capire con quale dei programmi
in commercio è stato realizzato un determinato file cifrato e
procurarselo. Se non fosse possibile le cose si complicano
notevolmente. Basandosi però sul fatto che anche il governo
americano utilizza un programma con algoritmo pubblico, si
presume che sia quasi sempre possibile entrare in possesso del
programma cifrante/decifrante.
I punti 2, 3 e 4, saranno funzioni di un unico programma
che devono essere realizzati da un programmatore.
Nello specifico, il generatore di password può tentare 2
strade :
1. la generazione di tutte le parole di un dato
dizionario, se si presume che la password possa
avere a che fare con qualche parola di senso
compiuto (sebbene l'autore dovrebbe essere andato
contro le regole del buon senso nella scelta della
password);
2. la generazione di password seguendo un ordine
stabilito (es. a, b,...z, aa, ab... az, aaa,aab...aaz, ecc.)
Le password generate saranno introdotte nel programma di
decrittazione (o decifrante, ovvero quello del punto 1), dal
programma pilota, che si occupa di passargli la stringa di
caratteri generalmente chiamata password, come se venisse
inserita manualmente. L'operazione è semplicissima: sotto
Windows, basta sfruttare l'automation, se fornita dal programma
decifratore, oppure l'emulazione di tastiera che è sempre
61
La crittografia
effettuabile, via software, o nel peggiore dei casi, via hardware
attraverso altre macchine.
Prima di tentare una nuova password, è necessario avere
un feedback dei risultati, realizzabile dal programma del punto
4, il quale analizzerà il file decifrato per vederne i risultati e
ricercare almeno alcune parole nel dizionario per vedere se sono
di senso compiuto. Dato che la maggior parte dei programmi di
crittografia non eseguono la decrittazione se la password
inserita non è corretta, il programma di test dovrà dare il
consenso ad un nuovo tentativo di inserimento password qualora
non trovi nessun file decifrato in output. Qualora sia stato
creato dal programma di decifratura, dopo averlo analizzato si
dovranno prendere 2 scelte :
1. se viene trovata una o più parole di senso compiuto,
deve interrompere tutte le operazioni e mostrare
l'ultima password provata.
2. se non viene trovata alcuna parola di senso
compiuto, deve cancellare il file appena esaminato
ed avviare un nuovo tentativo di inserimento
password da parte del programma (o funzione)
pilota.
Il dizionario che viene sfruttato dal programma di test
(quello che genera quindi il feedback per il programma pilota),
dovrà contenere le parole più comuni della lingua che si
presume sia stata utilizzata, e sarà realizzato con un database
indicizzato, oppure da un file di testo da caricare completamente
in memoria per una più veloce operazione di ricerca. Tenere
presente che tale dizionario potrebbe comunque essere
composto anche solo da quelle congiunzioni, preposizioni, verbi
ecc., onnipresenti in un testo. Può quindi essere sufficiente
utilizzare un piccolo dizionario contenente parole formate da un
minimo 3 caratteri (per evitare interpretazioni di successo
errate, dovute al caso), come "dal", "che", "degli", "gli",
"anche", "per", "non", "essere", "avere", "fare", ecc.
Il sistema sopra esposto è specifico per i testi, ma può
andare bene anche per la decrittazione di programmi eseguibili
(software), dato che le interfacce utente dei programmi,
contengono sempre parole del linguaggio parlato.
Per la decrittazione di programmi eseguibili possono
tuttavia essere utilizzati particolari accorgimenti, tanto per
citarne uno, controllare solo i primi due byte del file decifrato,
verificando che contengano il valore esadecimale 4D-5A,
velocizzando le operazioni che in questo modo non necessitano
neanche più del dizionario.
3.7
Curiosità e considerazioni
Quanto potente deve essere un metodo crittografico per
stare tranquilli?
62
La crittografia
A questa domanda si può rispondere in due modi: la
risposta più ovvia sarebbe: "Più si va sul sicuro, meglio è".
D'altro canto, si potrebbe rispondere anche in maniera più
tecnica: "Il fine della crittografia, non è sempre quello di
rendere assolutamente impossibile la decifrazione, quanto quello
di proteggere nella misura in cui la decifrazione richiede più
tempo e risorse economiche del vantaggio che può portare la
conoscenza delle informazioni protette".
Se qualche secolo fa, un qualsiasi polialfabetico con
chiave di 4 cifre sarebbe stato considerato impossibile da
forzare, oggi c'è invece da preoccuparsi anche dei semplici
attacchi a forza bruta possibili solo grazie ai computer. In altre
parole, la sicurezza di un sistema crittografico deve aumentare
col passare del tempo. Se oggi utilizzassimo ancora un sistema
come il cifrario di Cesare, anche un ragazzino sarebbe in grado
di decifrare un messaggio ed il più lento dei computers (anche
uno dei primi 8086 o un 286) potrebbe trovare la soluzione in
qualche frazione di millesimo di secondo.
Fra una decina di anni, programmi ed algoritmi famosi
potranno essere forzati col semplice brute -force, grazie ai
miliardi di operazioni al secondo che già adesso alcuni PC sono
in grado di compiere. C’è chi dice che in ambiente Echelon la
crittografia DES ed altre a 64 bit siano decrittate in tempo
reale...
63
Esempi pratici
Capitolo 4
Esempi pratici
4.1
4.2
4.3
4.4
4.5
4.6
4.1
L’uso di Winsock
4.1.1
Struttura dell’applicazione
4.1.2
Implementazione dell’applicazione
Il DES
4.2.1
La classe CDes
Scambio di messaggi crittati
4.3.1
Struttura dell’applicazione
4.3.2
Implementazione dell’applicazione
L’ analisi di un testo
4.4.1
Struttura dell’applicazione
4.4.2
Implementazione dell’applicazione
I socket in Linux
4.5.1
Implementazione dell’applicazione
PGP
L’uso di Winsock
Questa applicazione sarà la base per creare un programma
che permetta l’invio di file crittati tra due terminali.
In particolare verranno usate le librerie Winsock che
forniscono gli strumenti necessarie per creare comunicazioni
tramite il protocollo TCP/IP.
Le API (Application Program Interface) Winsock sono
state programmate per fornire un’interfaccia uniforme per
l’esecuzione delle applicazioni di rete, indipendentemente dal
software di rete utilizzato.
4.1.1
Struttura dell’applicazione
L’applicazione è strutturata a finestre di dialogo. Ovvero
vi è la completa assenza di menu e barre di comando, questo per
rendere più pulita e semplice l’interfaccia e anche perché non se
ne è resa necessaria l’inclusione nel progetto.
L’interfaccia offre la possibilità di digitare l’indirizzo del
server con cui comunicare (può anche essere un server di
loopback, cioè la macchina stessa) e la porta da cui effettuare la
scelta. Fatto questo basta cliccare sul pulsante Connect (Listen
se è un server) per cominciare la comunicazione.
Per quanto riguarda il funzionamento dell’applicazione ci
sono due modi principali : client e server.
64
Esempi pratici
Quando l’applicazione lavora come server essa si mette in
ascolto di eventuali richieste da parte del client, mentre quando
è in modo client l’applicazione dovrà attendere che il server si
metta in ascolto per iniziare a comunicare.
Indirizzo server e n° porta
Apertura,
chiusura
connessione
Tipo socket (client,server)
Testo del
messaggio
Invia messaggio
Messaggi inviati
Messaggi ricevuti
Figura 4.1 : Schema dell’applicazione PTerminal.
Indirizzo server e numero porta
Questi due campi sono riservati all’inserimento
dell’indirizzo del server e il numero della porta a cui ci si vuole
collegare o da cui ci si vuole mettere in ascolto, nel caso si sia
client o server. È indispensabile completare entrambe i campi
per aprire un socket.
Tipo socket
Queste due opzioni servono per scegliere se l’applicazione
deve fare da server o da client. A seconda della scelta il
comportamento dell’applicazione varierà.
Apertura, chiusura connessione
Questi due pulsanti permettono di creare la connessione e
di abbatterla. Nel caso il computer è stato configurato come
server il pulsante Connect diventa Listen, per sottolineare il
fatto che l’applicazione, da quel momento, si metterà in ascolto
di eventuali richieste da parte di un client.
Testo del messaggio
Questo campo è riservato al testo del messaggio. Sia il
client che il server possono ricevere e mandare messaggi.
65
Esempi pratici
Invia messaggio
Questo pulsante permette di inviare il messaggio scritto
nel campo testo del messaggio. Nel caso in cui il campo sia
vuoto non verrà inviato nulla.
Messaggi inviati, messaggi ricevuti
In queste due finestre viene tenuto l’ordine di ricezione e
di spedizione dei messaggi.
4.1.2
Implementazione dell’applicazione
Come accennato in precedenza per la realizzazione
dell’applicazione sono state utilizzate le API Winsock. Di
seguito è riportata una breve descrizione dei metodi e degli
eventi principali.
Metodo Create
Questo metodo prepara il socket per l’uso. La
dichiarazione del metodo cambia a seconda che il computer sia
client o server. Nel caso sia server occorre specificare anche
l’indirizzo della porta in ascolto. Nel caso sia client non occorre
specificare nessun parametro.
Metodo Connect
Questo metodo apre fisicamente la connessione. È
utilizzata solamente dal lato client.
Il client, per aprire la connessione, deve specificare il
l’indirizzo IP del server e il numero della porta.
Metodo Listen
Questo metodo, utilizzato solamente dal lato server,
abilita il server a ricevere chiamate.
Il metodo Listen non ha bisogno di parametri.
Metodo Accept
Questo metodo viene richiamato in seguito all’evento
OnAccept. Il socket in ascolto, all’arrivo della chiamata, creerà
un ulteriore socket connesso all’altra applicazione. Per questo
socket non bisognerà richiamare il metodo Create ma il metodo
Accept.
Il metodo Accept vuole come parametro la variabile
associata all’altra applicazione.
Metodo Send
Questa primitiva permette l’invio dei messaggi attraverso
una connessione via socket. Il metodo è identico per il client e
per il server.
I parametri indispensabili sono un puntatore ad un buffer
generico e la lunghezza dello stesso. Questi parametri sono
indispensabili perché il socket non conosce il tipo di dati da
inviare.
66
Esempi pratici
Metodo Receive
Questa primitiva viene attivata dall’evento OnReceive.
Grazie all’evento il socket sa che ci sono messaggi in coda. I
parametri sono i medesimi del metodo Send, un puntatore ad un
buffer e la sua lunghezza.
Metodo Close
È comune al socket e al client. Non vuole nessun
parametro, inoltre è anche l’unico metodo a non restituire un
codice di errore.
Evento OnAccept
Questo evento viene scatenato all’arrivo di una chiamata al
socket in ascolto.
Evento OnClose
Questo evento viene scatenato all’arrivo di una
segnalazione di chiusura (metodo Close) da parte di una delle
due applicazioni.
Evento OnConnect
Questo evento viene scatenato in un socket per segnalare
l’avvenuta connessione.
Evento OnReceive
Questo evento viene scatenato all’arrivo di un messaggio.
Evento OnSend
Questo evento è richiamato quando il socket è pronto a
inviare dati.
Di seguito verrà descritta l’implementazione della classe
per la gestione dei socket.
La classe creata è stata derivata dalla classe MFC
CAsyncSocket. In questo modo è possibile ereditare la gestione
degli eventi dalla classe MFC personalizzando quelli interessati.
class CMySocket : public CAsyncSocket
{
private:
CDialog* m_pWnd;
public:
CMySocket();
virtual ~CMySocket();
SetParent (CDialog *pWnd);
virtual void OnAccept(int nErrorCode);
virtual void OnConnect(int nErrorCode);
virtual void OnReceive(int nErrorCode);
};
67
Esempi pratici
Le variabili
La variabile m_pWnd è un puntatore alla finestra di
dialogo corrente.
I metodi
Funzione SetParent
PROTOTIPO
SetParent (CDialog *pWnd)
INPUT
pWnd
puntatore ad una finestra di dialogo
DESCRIZIONE
La funzione setta la variabile privata m_pWnd con la
variabile passata come parametro.
Funzioni OnAccept, OnConnect, OnReceive
PROTOTIPO
virtual void Onxxxxx ( int nErrorCode )
INPUT
nErrorCode
codice errore
DESCRIZIONE
Queste funzioni rispondo agli eventi di base della
classe. Esse sono state derivate da quelle definite nella classe
CAsyncSocket. La loro funzione è quella di richiamare i metodi
standard della classe per soddisfare le richieste dei socket.
4.2
Il DES
Il funzionamento del DES è stato ampiamente descritto
nel capitolo precedente, di conseguenza, di seguito, verrà
analizzata l’implementazione in C. In particolare saranno
esaminate le classi e i metodi utilizzati.
Al termine, la classe creata, è stata inserita in una DLL
(Dynamic Linked Library) in modo da permetterne il
funzionamento congiunto con altre applicazioni.
Nel nostro caso, la DLL, sarà usata insieme ad
un’applicazione per l’invio di messaggi attraverso TCP/IP, in
modo da rendere possibile lo scambio di messaggi crittati.
4.2.1
La classe CDes
La classe CDes contiene i metodi e le variabili che
caratterizzano l’algoritmo DES.
class CDes
{
public:
CDes();
virtual ~CDes();
68
Esempi pratici
void Crypt(LPTSTR Key, LPTSTR Data);
void Decrypt(LPTSTR Key, LPTSTR Data);
private:
unsigned _int64 artoi(unsigned int *array,unsigned int length);
void itoar(unsigned __int64 int64,unsigned int *array,unsigned int length);
unsigned _int64 stoi(char *string,unsigned int length);
void matoar32(unsigned int matrix[][4],unsigned int array[],unsigned int yStart,unsigned int
xStart,unsigned int yEnd,unsigned int xEnd);
void matoar48(unsigned int matrix[][6],unsigned int array[],unsigned int yStart,unsigned int
xStart,unsigned int yEnd,unsigned int xEnd);
void matoar56(unsigned int matrix[][7],unsigned int array[],unsigned int yStart,unsigned int
xStart,unsigned int yEnd,unsigned int xEnd);
void matoar64(unsigned int matrix[][8],unsigned int array[],unsigned int yStart,unsigned int
xStart,unsigned int yEnd,unsigned int xEnd);
void _strcat(char *strDest,char *strOr);
void arcat(unsigned int *arrayOr1,unsigned int *arrayOr2,unsigned int *arrayDest,unsigned int
lenDest,unsigned int lenOr);
unsigned _int64 power(unsigned int b,unsigned int e);
void shift(unsigned __int64 &shift,unsigned int nShift);
void Calculate_Keys(unsigned int matrix[][7],unsigned int iterations);
unsigned __int64 crypt(unsigned __int64 data,unsigned int iterations);
unsigned __int64 crypt(unsigned __int64 data,unsigned int iterations);
void Divide(unsigned int *array,unsigned int matrix[][6],unsigned int lenAr,unsigned int
lenGrp);
unsigned int Index(unsigned matDiv[][6],unsigned matrix[][16],unsigned row);
void Group(unsigned int *array,unsigned int *arrGrp,unsigned int lenAr,unsigned int lenGrp);
void Expand(unsigned int *array,unsigned int matrix[][6]);
void Permute_IP(unsigned int *array,unsigned int matrix[][8]);
void Permute_P2(unsigned int *array,unsigned int matrix[][4]);
void Permute_FP(unsigned int *array,unsigned int matrix[][8]);
void Reduce56to48(unsigned int *array,unsigned int matrix[][6]);
void Reduce64to56(unsigned int *array,unsigned int matrix[][7]);
void Set_Key(unsigned __int64 newKey);
unsigned EX[8][6];
unsigned FP[8][8];
unsigned IP[8][8];
unsigned __int64 Keys_Array[16];
unsigned __int64 L[17];
unsigned P1[8][6];
unsigned P2[8][4];
unsigned __int64 R[17];
unsigned Rotation_Array[16];
unsigned R1[8][7];
unsigned S1[4][16];
unsigned S2[4][16];
unsigned S3[4][16];
unsigned S4[4][16];
unsigned S5[4][16];
unsigned S6[4][16];
unsigned S7[4][16];
unsigned S8[4][16];
unsigned _int64 Key;
};
69
Esempi pratici
I metodi e le variabili della classe sono dichiarati tutti
privati, ad eccezione dei due metodi che permettono la cifratura
e la decifratura dei dati. Questo è stato fatto per evitare che ci
possa essere un “furto” di dati dall’ esterno.
Le variabili
Le variabili EX, FP, IP, P1, P2, R1 e Sx sono matrici
predefinite che servono nello sviluppo dell’algoritmo per
calcolare sia le 16 chiavi che la cifratura del blocco dati.
La variabile Rotation_Array è un array contenente il
numero di rotazioni da effettuare per ogni iterazione.
La variabile Keys_Array è un array che contiene le 16
chiavi di sovracifratura da applicare al blocco dati.
Le variabili L e R sono matrici che contengono gli sviluppi
dei 16 passi di cifratura.
La variabile Key contiene la chiave di cifratura.
I metodi
Funzione Calculate_Keys
PROTOTIPO
void Calculate_Keys(unsigned int matrix[][7],
unsigned int iterations)
INPUT
matrix[][7]
matrice ridotta
iterations
iterazioni
DESCRIZIONE
La funzione calcola le chiavi usate per la crittazione. Il
numero di chiavi da calcolare è definito dalla variabile
iterations.
Funzione crypt
PROTOTIPO
unsigned __int64 crypt(unsigned __int64 data,
unsigned int iterations)
INPUT
data
dati da cifrare
iterations
iterazioni
OUTPUT
iRes
dati cifrati
DESCRIZIONE
La funzione critta il dato passato. La variabile iterations
indica, implicitamente, il numero di chiavi da usare per la
cifratura.
Funzione decrypt
PROTOTIPO
unsigned __int64 decrypt(unsigned __int64 data,
unsigned int iterations)
70
Esempi pratici
INPUT
data
dati da decifrare
iterations
iterazioni
OUTPUT
iRes
dati decifrati
DESCRIZIONE
La funzione decritta il dato passato. La variabile
iterations indica, implicitamente, il numero di chiavi da usare
per la decifratura.
Funzione artoi
PROTOTIPO
unsigned __int64 artoi(unsigned int *array,
unsigned int length)
INPUT
array
array da convertire
length
lunghezza dell'array
OUTPUT
iRes
array convertito
DESCRIZIONE
La funzione converte un array binario (composto da 0 o 1)
in un intero a 64 bit. La funzione non effettua nessun controllo
sulla lunghezza dell'array, ma è implicito che esso non debba
superare i 64 byte. Di conseguenza ogni controllo deve essere
effettuato prima della chiamata alla funzione.
Funzione itoar
PROTOTIPO
void itoar(unsigned __int64 int64, unsigned int *array,
unsigned int length)
INPUT
int64
intero da convetire
array
array in cui inserire l'intero convertito
length
lunghezza dell'array
DESCRIZIONE
La funzione converte un intero fino a 64 bit in un array
binario (composto da 0 e 1). La funzione non effettua nessun
controllo sulla lunghezza dell'array, ma è implicito che esso
debba essere lungo tanto quanto la variabile da convertire e
non più del tipo più grande (unsigned __int64). Di conseguenza
ogni controllo deve essere effettuato prima della chiamata alla
funzione.
Funzione stoi
PROTOTIPO
void stoi(char *string, unsigned int length)
INPUT
string
stringa da convertire
length
lunghezza della stringa
OUTPUT
iRes
stringa convertita
71
Esempi pratici
DESCRIZIONE
La funzione converte una stringa in un intero a 64 bit. La
funzione non effettua nessun controllo sulla lunghezza della
stringa, ma è implicito che essa non debba superare i 64 byte. Di
conseguenza ogni controllo deve essere effettuato prima della
chiamata alla funzione.
Funzioni matoarXX
PROTOTIPO
void matoarXX(unsigned int matrix[][X],
unsigned int *array,
unsigned int yStart,
unsigned int xStart,
unsigned int yEnd,
unsigned int xEnd)
INPUT
matrix[][x]
matrice da convertire
array
array risultato
yStart
riga di partenza
xStart
colonna di partenza
yEnd
riga di arrivo
xEnd
colonna di arrivo
DESCRIZIONE
Le funzioni convertono una matrice di n righe e m
colonne, in un array pari alla loro dimensione.
I parametri indicano implicitamente il numero di elementi
da estrarre dalla matrice.
La funzione non effettua nessun controllo sulla lunghezza
dell' array che deve essere di lunghezza minima pari alla
grandezza della matrice. Di conseguenza ogni controllo deve
essere effettuato prima della chiamata alla funzione.
Funzione power
PROTOTIPO
unsigned __int64 power(unsigned int b, unsigned int e)
INPUT
b
base
e
esponente
OUTPUT
x
risultato
DESCRIZIONE
La funzione calcola l'elevamento a potenza. Sia la base che
l'esponente devono essere non negativi.
Funzione shift
PROTOTIPO
void shift(unsigned __int64 &shift,
unsigned int nShift)
INPUT
Shift
valore da shiftare
nShift
numero di shift (1 o 2)
72
Esempi pratici
OUTPUT
shift
valore shiftato
DESCRIZIONE
La funzione simula uno shift circolare supponendo che
l'intero passato come parametro sia di soli 6 bit.
Funzione arcat
PROTOTIPO
void arcat(unsigned int *arrayOr1,
unsigned int *arrayOr2,
unsigned int *arrayDest,
unsigned int lenOr1, unsigned int lenOr2)
INPUT
arrayOr1
primo array da concatenare
arrayOr2
secondo array da concatenare
arrayDest
array risultato
lenOr1
lunghezza del primo array
lenOr2
lunghezza del secondo array
DESCRIZIONE
La funzione concatena due array della lunghezza
specificata dai parametri lenOr1 e lenOr2. La funzione non
effettua il controllo sulla lunghezza degli array, di conseguenza
tutti i controlli devono essere fatti prima della chiamata alla
funzione.
Funzione _strcat
PROTOTIPO
void _strcat(char *strDest, char *strOr)
INPUT
strDest
stringa destinazione
strOr
stringa d'origine
DESCRIZIONE
La funzione concatena due stringhe. La stringa risultante
sarà contenuta in strDest, inoltre essa sarà del tipo nullterminated.
Funzioni di riduzione, espansione e permutazione
PROTOTIPO
void NOME_FUNZIONE(unsigned int *array,
unsigned int matrix[][x])
INPUT
array
array a cui applicare la matrice
matrix[][x]
matrice risultante
DESCRIZIONE
Le funzioni applicano la matrice specificata, costruendone
una risultante dall'operazione. Le funzioni seguono lo stesso
principio di funzionamento, cambia solo la matrice applicata (le
matrici si differenziano, oltre che per i valori, anche per la
grandezza).
Di seguito sono riassunte le funzioni con le matrici applicate.
Reduce56to48
P1 = prima matrice di permutazione
Reduce64to56
R1 = matrice di riduzione
73
Esempi pratici
Permute_IP
Permute_P2
Permute_FP
Expand
IP = matrice di permutazione iniziale
P2 = seconda matrice di permutazione
FP = matrice di permutazione finale
EX = matrice di espansione
Funzione Divide
PROTOTIPO
void Divide(unsigned int *array,
unsigned int matrix[][6],
unsigned int lenAr,
unsigned int lenGrp)
INPUT
array
array da dividere
matrix
matrice risultato
lenAr
lunghezza array
lenGrp
lunghezza gruppo
DESCRIZIONE
La funzione divide un array in gruppi della lunghezza
specificata dalla variabile lenGrp. La massima grandezza
dell'array è di 48 byte, di conseguenza la grandezza massima
della matrice sarà 8*6. La funzione non effettua nessun
controllo sulla lunghezza dell'array e sulla grandezza della
matrice. Di conseguenza ogni controllo deve essere fatto prima
della chiamata alla funzione.
Funzione Group
PROTOTIPO
void Group(unsigned int *array,
unsigned int *arrayGrp,
unsigned int lenAr,
unsigned int lenGrp)
INPUT
array
array da raggruppare
arrayGrp
array risultato
lenAr
lunghezza array
lenGrp
lunghezza dei gruppi
DESCRIZIONE
La funzione unisce un array di interi (NON binario) in un
unico array. La lunghezza dell'array e quella dei gruppi di bit
viene passata come parametro.
Funzione Index
PROTOTIPO
unsigned Index(unsigned int matDiv[][6],
unsigned int matrix[][6],
unsigned row)
INPUT
matDiv[][6]
matrice da indicizzare
matrix
matrice da cui estrarre i dati
row
riga della matrice da indicizzare
OUTPUT
iRes
risultato
74
Esempi pratici
DESCRIZIONE
La funzione preleva dalla matrice matDiv il valore binario
e lo converte in modo da comporre le coordinate di ricerca (m =
colonna, n = riga). L'intero risultato della ricerca verrà
restituito.
Funzione Set_Key
PROTOTIPO
void Set_Key(unsigned __int64 newKey)
INPUT
newKey
nuova chiave
DESCRIZIONE
Funzione di interfaccia che setta la chiave.
Funzioni Crypt e Decrypt
PROTOTIPI
void Crypt(LPTSTR Key, LPTSTR Data)
void Decrypt(LPTSTR Key, LPTSTR Data)
INPUT
key
chiave
data
dati da elaborare
DESCRIZIONE
Le funzioni sono i metodi principali della classe, servono
per crittare e decrittare i dati.
Il loro funzionamento è analogo, infatti la funzione
Decrypt non fa che ripercorrere i passi della funzione Crypt al
contrario.
Ambedue le funzioni dividono i dati passati come stringhe
in gruppi di 8 byte, in seguito, il gruppo appena ottenuto, viene
crittato usando le 16 chavi precedentemente calcolate. I risultati
vengono concatenati in un’ unica stringa e copiati nella stringa
Data.
4.3
Scambio di messaggi crittati
L’applicazione unisce l’uso di WinSock con la DLL
costruita in precedenza per l’uso del DES.
Attraverso questa applicazione sarà possibile mandare dei
messaggi crittati attraverso l’algoritmo DES, tra un client e un
server.
Le finestre di dialogo dell’applicazione sono le medesime
usate per l’applicazione PTerminal. Quindi sarà possibile
scegliere la porta da cui effettuare lo scambio di informazioni e
chi sarà il server e chi il client.
La crittazione del messaggio avverrà in trasparenza, infatti
il messaggio inserito dall’utente verrà crittato prima dell’invio e,
di conseguenza, decrittato prima della visualizzazione che
avverrà sul computer del secondo utente.
La chiave dovrà essere già concordata in precedenza tra gli
utenti.
75
Esempi pratici
4.3.1
Struttura dell’applicazione
La struttura dell’applicazione è identica a quella di
PTerminal.
Figura 4.2 : Schema dell’applicazione.
Come si può notare l’applicazione è strutturata in modo
compatto. Non sono presenti menu ma solo un gruppo di Radio
Button per decidere quale applicazione deve essere il server e
quale il client.
I tre Edit Box servono per inserire l’indirizzo del server e
la porta a cui connettersi, l’ultimo serve per inserire i messaggi
da inviare.
I tre Command Button servono per aprire una
connessione, chiuderla e per mandare il messaggio.
Le due List Box servono per tenere traccia dei messaggi
inviati e ricevuti.
4.3.2
Implementazione dell’applicazione
La realizzazione dell’applicazione ha richiesto
l’implementazione di una sola classe, oltre a quella usata per il
DES. Essa è stata derivata dalla classe CAsyncSocket delle MFC.
Ciò è stato reso necessario per gestire alcuni eventi particolari
all’interno della classe, come l’invio e la ricezione. A questa
classe è stato dato il nome CMySocket.
76
Esempi pratici
Per l’aggiunta delle funzionalità di crittazione e
decrittazione all’applicazione è stata usata la DLL creata in
precedenza. L’aggiunta al progetto della DLL CDes ha richiesto
solamente la dichiarazione, all’interno della classe
CPTerminalDlg, del file header relativo alla DLL e l’aggiunta al
progetto, come nuova risorsa, del file LIB della DLL.
L’unica modifica al codice di PTerminal è stata l’aggiunta
di un oggetto CDes nella classe CPTerminalDlg. Inoltre sia in
ricezione che in invio, la stringa di dati viene passata al metodo
Decrypt o Crypt, in modo da crittare/decrittare la stringa.
Oggetti, variabili ed eventi
I seguenti oggetti sono definiti nel progetto, alcuni di essi
hanno associata una variabile.
• IDC_RCLTSRV
(Radio Button)
VARIABILE
int m_iType
• IDC_LSENT
(List Box)
VARIABILE
CListBox m_ctlSent
• IDC_LRCVD
(List Box)
VARIABILE
CListBox m_ctlRcvd
• IDC_ESRVPORT (Edit Box)
VARIABILE
int m_iPort
• IDC_ESRVNAME (Edit Box)
VARIABILE
CString m_strName
• IDC_EMSG
(Edit Box)
VARIABILE
CString m_strMessage
• IDC_BCONNECT (Command Button)
VARIABILE
CButton m_ctlConnect
• IDC_BSEND
(Command Button)
• IDC_BCLOSE
(Command Button)
I pulsanti IDC_BSEND e ICD_BCONNECT sono collegati
a due eventi della classe CPTerminalDlg, OnBSend e
OnBConnect. Questi due eventi creano la connessione e inviano
i messaggi. Per la ricezione dei messaggi si usa la funzione
Receive che viene richiamata ogniqualvolta viene generato
l’evento OnReceive.
Tutti questi eventi sono stati già definiti nelle classi
CPTerminal e CMySocket nel progetto PTerminal.
77
Esempi pratici
4.4
Analisi di un testo
In questa applicazione si cercherà di analizzare un testo
cifrato e di decifrarlo senza avere la chiave. Per lo scopo si
utilizzeranno tabelle contenenti le frequenze delle lettere della
lingua italiana. Riportando questi valori a quelli relativi alle
lettere contenute nel testo si potrà ricavare il testo in chiaro.
Inoltre l’applicazione, sviluppata in Visual Basic, permetterà
l’uso di algoritmi di cifratura di base (cifrario di Cesare,
scacchiera di Polibio, cifrario di Vigénère).
4.4.1
Struttura dell’applicazione
L’applicazione è strutturata come una tipica applicazione
MDI (Multiple Document Interface). Vi è una form principale
contenente il menu delle opzioni e la barra di comando, in più vi
sono due form secondarie, una usata per la visualizzazione e
l’editazione del testo, mentre l’altra per visualizzare attraverso
un grafico le frequenze delle lettere presenti nel testo.
Barra dei menu
Barra di comando
Testo
Grafico delle frequenze
Barra di stato
Figura 4.3 : Schema dell’applicazione crittografia.
78
Esempi pratici
La barra dei menu
La barra dei menu è costituita da quattro voci principali :
• File
• Analizza
• Critta
• Decritta
Attraverso queste voci è possibile effettuare tutte le
operazioni permesse dall’applicazione.
Menu file
Figura 4.4 : Menu file
dell’applicazione Crittografia.
Dal menu file è possibile scegliere le seguenti opzioni :
• Apri file in chiaro
Questa opzione permette di aprire un file di
qualsiasi estensione, visualizzandone il contenuto
nella finestra di visualizzazione dei documenti.
• Salva file in chiaro
Questa opzione permette di salvare un file appena
editato senza applicare nessuna crittografia.
Inoltre, se il file da salvare è un file crittato,
l’applicazione lo decritta automaticamente e lo
salva in un formato definito dall’utente (il formato
di default è il txt).
• Apri file crittato
Questa opzione permette di aprire un file
precedentemente crittato. I tre formati disponibili
sono :
o *.csr, cifrario di Cesare;
o *.plb, scacchiera di Polibio;
o *.vgn, cifrario di Vigénère.
Il file decrittato viene automaticamente
visualizzato nella finestra di visualizzazione
documenti.
• Salva file crittato
Questa opzione permette di salvare un testo
oppure un file aperto in chiaro, usando uno dei tre
algoritmi a disposizione (cifrario di Cesare,
scacchiera di Polibio, cifrario di Vigénère).
79
Esempi pratici
Menu analizza
Questo menu non ha sottomenu. Se non è stato aperto
nessun file, l’applicazione, chiede di aprirne uno e viene
automaticamente visualizzato il grafico delle frequenze delle
lettere. Al contrario, se un file è già stato aperto e nessun
grafico è visualizzato a schermo, viene aperta una nuova finestra
contenente il grafico della frequenza delle lettere.
Menu critta
Figura 4.5 : Menu critta
dell’applicazione
Crittografia.
Dal menu critta è possibile scegliere uno dei seguenti
algoritmi di crittazione :
• Cifrario di Cesare
• Scacchiera di Polibio
• Cifrario di Vigénère
Scegliendo uno di questi algoritmi, il testo contenuto nella
finestra di visualizzazione testo, viene crittato. Per salvarlo
basta scegliere dal menu File Salva file crittato. In questo modo
l’applicazione riconoscerà automaticamente l’algoritmo di
crittazione utilizzato e di conseguenza salverà il file con
l’estensione appropriata. L’utente dovrà solamente scegliere il
nome da dare al file.
Menu decritta
Figura 4.6 : Menu
decritta
dell’applicazione
Crittografia.
Dal menu decritta è possibile scegliere l’algoritmo da
utilizzare per decrittare il file :
• Cifrario di Cesare
• Scacchiera di Polibio
• Cifrario di Vigénère
Scegliendo uno di questi algoritmi, il testo contenuto nella
finestra di visualizzazione del testo, viene decrittato. Come
succede per la crittazione, se si vuole salvare il file appena
decrittato, basta selezionare dal menu File Salva file in chiaro.
Così facendo, l’applicazione, salverà automaticamente il file nel
formato preferito dall’utente.
80
Esempi pratici
La barra di comando
Apri file in chiaro
Salva file in chiaro
Figura 4.7 : Barra di
comando
dell’applicazione
Crittografia.
Salva file crittato
Nuovo documento
Apri file crittato
La barra di comando riassume tutte le funzioni principali
contenute nel menu file, con in più un ulteriore opzione, quella
di creare un nuovo documento vuoto.
La barra di stato
Figura 4.8 : Barra di stato dell’applicazione Crittografia.
La barra di stato contiene il percorso del file
correntemente aperto.
4.4.2
Implementazione dell’applicazione
Le form
Per realizzare l’applicazione sono state utilizzate tre form
principali :
• mdiMain
• frmDoc
• frmGraph
La form principale è una form MDI, che può gestire un
numero elevato di form figlie. In questo modo è possibile
visualizzare più finestre documento o grafico
contemporaneamente.
Le altre due form sono dei modelli. Ogni qualvolta viene
richiesto un nuovo documento o un nuovo grafico ne viene
creata una nuova. Il metodo di creazione è il seguente :
Dim nome_form as frmDoc (o frmGraph)
Form mdiMain
Come detto in precedenza è la form principale. Essa
contiene il menu, la barra di comando e quella di stato. In più
permette la visualizzazione dei grafici e dei testi.
Gli oggetti utilizzati al suo interno sono i seguenti :
• tlbMain (Toolbar)
Toolbar (barra di comando).
Evento on-click.
81
Esempi pratici
•
•
•
stbMain (StatusBar)
Statusbar (barra di stato).
imlTlb (ImageList)
Controllo che contiene le immagini delle icone
presenti sulla barra di comando.
cdlSaveOpen (CommonDialog)
Controllo che permette l’utilizzo delle finestre
standard per il salvataggio e il caricamento dei
file.
Funzioni
Le funzioni descritte di seguito sono quelle usate per il
salvataggio, l’apertura e il calcolo delle frequenze delle lettere.
Le funzioni relativi agli eventi non saranno descritte.
Funzione Scan
PROTOTIPO
Private Function Scan (strC as String) as Boolean
INPUT
strC
carattere da cercare
OUTPUT
vero
il carattere è stato trovato
falso
il carattere non è stato trovato
DESCRIZIONE
La funzione calcola la frequenza delle lettere nel testo,
che verranno rappresentate nel grafico.
Funzione OpenFile
PROTOTIPO
Private Function OpenFile (strFileToOpen as String)
as String
INPUT
strFileToOpen
percorso del file da aprire
OUTPUT
strFileOpen
stringa contenente il file aperto
DESCRIZIONE
La funzione apre il file specificato dalla stringa
strFileToOpen. Per gestire i file è stato usato l’oggetto
FileSystemObject, il quale permette di creare dei file di testo. In
questo modo sono disponibili dei metodi di lettura e scrittura
più veloci e più semplici da utilizzare.
Funzione SaveFile
PROTOTIPO
Private Function SaveFile (strFileToSave as String,
strFileSave as string)
as Boolean
INPUT
strFileToSave
percorso in cui salvare il file
strFileSave
stringa da salvare
82
Esempi pratici
OUTPUT
vero
il file è stato salvato
falso
il file non è stato salvato
DESCRIZIONE
La funzione salva la stringa passata su file. Anche in
questo caso la gestione del file avviene attraverso l’oggetto
FileSystemObject.
Funzioni menu
Queste funzioni vengono richiamate quando accade
l’evento on_click su uno dei menu. Il loro compito è quello di
richiamare le funzioni per la gestione dei file e per la cifratura e
decifratura.
Funzioni SaveCyph, OpenCyph, SaveClear, OpenClear
Queste funzioni vengono utilizzate per impostare i filtri
del CommonDialog e per scegliere che modalità utilizzarlo
(Open o Save).
Form frmDoc
Questa form è usata come modello per tutte quelle che
verranno create per la visualizzazione dei documenti.
Gli oggetti utilizzati all’interno sono i seguenti :
• txtText (TextBox)
TextBox utilizzata per la visualizzazione dei
documenti.
All’intero non sono state definite funzioni.
L’unico evento a cui risponderà la form sarà l’evento
Resize. In questo modo la TextBox manterrà dimensioni costanti
anche dopo il ridimensionamento della form.
Form frmGraph
Questa form è usata come modello per tutti i grafici delle
frequenze.
Gli oggetti utilizzati all’interno sono i seguenti :
• mscGraph (MSChart)
Oggetto utilizzato per la creazione del grafico.
Come nella precedente form, non sono state definite
funzioni. Anche in questo caso la form risponderà all’evento
Resize, in modo da mantenere la dimensione del grafico
costante.
83
Esempi pratici
Modulo modInit
Questo modulo contiene le inizializzazioni delle variabili,
le variabili stesse e altre funzioni per il settaggio del
CommonDialog.
Variabili
Le variabili globali definite all’interno del modulo sono :
• Public ALPHA(26) As String
Array contenente le lettere dell’alfabeto più lo
spazio.
• Public ASCII(255, 1) As String
Matrice contenente i 256 caratteri ASCII, ognuno
dei quali associato ad una frequenza.
• Public PLOT(26, 1)
Matrice contenente le lettere dell’alfabeto più lo
spazio. Ad ognuna di esse è associata una
frequenza.
• Public FREQ(26) As String
Array contenente le lettere dell’alfabeto in ordine
di frequenza rispetto alla lingua italiana.
• Public CaesarCyph As New Caesar
• Public PolibioCyph As New Polibio
• Public VigenereCyph As New Vigenere
Oggetti usati per la crittazione e la decrittazione.
Funzioni
Funzione InitVAR
PROTOTIPO
Public Sub InitVAR()
DESCRIZIONE
La funzione inizializza tutti gli array e le matrici con i
dati.
Funzione Clear
PROTOTIPO
Public Sub Clear()
DESCRIZIONE
Azzerra l’array PLOT.
Funzione InitCDL
PROTOTIPO
Public Sub InitCDL(CDL as CommonDialog,
strExt as String, strTitle as String,
strFilter as String,
strInitDir as String,
strOpenSave as String)
INPUT
CDL
oggetto da settare
84
Esempi pratici
strExt
estensione standard da dare ai file
strTitle
titolo che apparirà nel CommonDialog
strFilter
possibili estensioni da dare al file
strInitDir
directory di default
strOpenSave
settaggio dei flags.
DESCRIZIONE
La funzione setta con i parametri passati il
CommonDialog, anch’esso passato come parametro.
Funzioni InitDOC e InitGRAPH
PROTOTIPO
Public Sub Initxxx(strFilename as String)
INPUT
strFilename
nome del file che apparirà come titolo
della finestra
DESCRIZIONE
Queste due funzioni creano una nuova finestra
documento e una nuova finestra grafico.
Moduli di classe
I moduli di classe contengono le definizioni delle classi
usate per gli algoritmi di crittazione.
Modulo Caesar
Questo modulo contiene le definizioni dei metodi per la
cifratura attraverso il cifrario di Cesare. La crittazione dei dati
avviene utilizzando il codice ASCII e non l’alfabeto ordinario.
Variabili
L’unica variabile definita all’interno del modulo è la
seguente :
• Private Alphabet(255) as String
Array contenente il codice ASCII.
Funzioni
Funzioni Crypt e Decrypt
PROTOTIPI
Public Function (De)Crypt(iSph as Integer,
strCrypt as String) as String
INPUT
iSph
lettere di sfasamento dell’alfabeto
strCrpyt
stringa da crittare
OUTPUT
strCrypted
stringa crittata
DESCRIZIONE
Queste due funzioni crittano e decrittano la stringa
passata.
85
Esempi pratici
Funzione Find
PROTOTIPO
Private Function Find(vChar as Variant) as Integer
INPUT
vChar
carattere da cercare
OUTPUT
i
posizione del carattere nell’array
Alphabet
DESCRIZIONE
Questa funzione cerca nell’array Alphabet il carattere
passato come parametro.
Modulo Polibio
Questo modulo contiene le definizioni dei metodi per
applicare la scacchiera di Polibio. Anche in questo caso la
crittazione viene effettuata sull’intero codice ASCII.
Variabili
L’unica variabile definita all’interno del modulo è la
seguente :
• Private Alphabet(15, 15) as String
Matrice contenente il codice ASCII.
Funzioni
Funzioni Crypt e Decrypt
PROTOTIPO
Public Function (De)Crypt(strCrypt as String) as String
INPUT
strCrypt
stringa da crittare
OUTPUT
strCrypted
stringa crittata
DESCRIZIONE
Queste due funzioni crittano e decrittano la stringa
passata come parametro. In questo caso il risultato della
crittazione non sarà una stringa alfabetica ma una stringa
alfanumerica. Infatti viene usato il codice esadecimale per
definire le righe e le colonne.
Funzione Find
PROTOTIPO
Private Sub Find(vChar as Variant, ByRef iY as Integer,
ByRef iX as Integer)
INPUT
vChar
carattere da cercare
OUTPUT
iY, iX
colonna e riga in cui si trova il
carattere
86
Esempi pratici
DESCRIZIONE
La funzione cerca nella matrice Alphabet il carattere
passato e ritorna il valore di riga e colonna nelle due variabili iY
e iX.
Modulo Vigénère
Questo modulo contiene le definizioni dei metodi per
applicare il cifrario di Vigénère. Anche in questo caso il la
crittazione è effettuata sull’intero codice ASCII.
Nel cifrario di Vigénère viene utilizzata anche una chiave
che in ogni crittazione/decrittazione verrà richiesta
dall’applicazione.
Variabili
L’unica variabile definita all’interno del modulo è la
seguente :
• Private Alphabet(15, 15) as String
Matrice contenente il codice ASCII.
Funzioni
Funzioni Crypt e Decrypt
PROTOTIPI
Private Function (De)Crypt(strCrypt as String,
strKey as String) as String
INPUT
strCrypt
stringa da crittare
strKey
chiave
OUTPUT
strCrypted
stringa crittata
DESCRIZIONE
Queste due funzioni crittano e decrittano la stringa
passata come parametro usando la chiave.
Funzioni FindRow e FindCol
PROTOTIPI
Private Sub Findxxx(vChar as Variant, y as Integer
x as Integer, ByRef iY as Integer
ByRef iX as Integer)
INPUT
vChar
carattere da cercare
y,x
colonna e riga di partenza
OUTPUT
iY,iX
colonna e riga in cui si trova il
carattere
DESCRIZIONE
Queste due funzioni cercano un carattere sulla linea e
sulla colonna passate come parametro.
87
Esempi pratici
4.5
I socket in Linux
Al fine di studiare più approfonditamente il protocollo
TCP/IP è stato creato un programma che simula una trama del
protocollo TCP/IP usato per la comunicazione tra le reti, sia
locali che geografiche.
Per poter gestire una trama TCP/IP, non è stato possibile
usare un compilatore di Windows, poiché esso non permette la
gestione a basso livello delle trame. Di conseguenza l’unico
modo per controllare i flag del protocollo TCP/IP è stato creare
un programma in C proprio del sistema operativo Linux. Infatti
esso permette, tramite l’uso dei socket raw, l’uso di funzioni che
permettono la gestione diretta delle trame di ricezione e invio.
Nel programma si è voluto simulare l’invio di una trama di
fine connessione, ossia con il FLAG di FIN =1.
All’inizio il programma crea l’header dell’IP ,
successivamente realizza l’header del TCP della trama che si
vuole inviare. Vengono inoltre calcolati i checksum del
pacchetto IP e anche dell’header TCP.
Parametri del programma
Il programma richiede dei parametri in input:
1. porta sorgente
2. indirizzo sorgente
3. porta destinazione
4. indirizzo destinazione
Senza questi parametri il programma non può funzionare,
causando un segnale d’errore :
“usare: porta_sorg. indirizzo sorg. porta dest. indirizzo
sorg.”
4.5.1
Implementazione dell’applicazione
Di seguito verranno descritte le funzioni più importanti
usate nel programma.
Funzioni
Funzione tcp_gen
PROTOTIPO
void tcp_gen(char *packet, unsigned short sport,
unsigned short dport, unsigned long seq,
unsigned long ack)
INPUT
packet
puntatore alla struttura IP
sport
porta sorgente
dport
porta destinazione
seq
numero di sequenza
ack
acknowledge
88
Esempi pratici
DESCRIZIONE
È la routine che compone un pacchetto TCP compilando
la struttura tcp contenuta nell'header del programma. Questa
routine setta il bit di fin a 1 indicando la chiusura della
connessione. Dopo aver compilato la struttura la routine
calcola il checksum sul pacchetto tcp.
Funzione ip_gen
PROTOTIPO
void ip_gen(char *packet,unsigned char protocol,
struct in_addr saddr,
struct in_addr daddr,
unsigned short length
INPUT
packet
pacchetto, rappresentato dal vettore
protocol
costante IPPROTO. Indica il
protocollo di livello di trasporto per la
compilazione della struttura IP
saddr
indirizzo sorgente
daddr
indirizzo destinazione
length
dimensione del pacchetto vettore
DESCRIZIONE
È la routine che compone l'header IP compilando la
struttura tcp contenuta nell'header del programma.
Dopo aver compilato la struttura la routine calcola il
cheksum sul pacchetto IP.
Funzione trans_check
PROTOTIPO
unsigned short trans_check(unsigned char proto,
char *packet, int length,
struct in_addr source_address,
struct in_addr dest_address)
INPUT
proto
protocollo utilizzato
packet
puntatore della struttura del TCP
header
length
lunghezza dell’header TCP
source_address indirizzo sorgente
dest_address
indirizzo destinazione
OUTPUT
La funzione calcola il checksum sul TCP header, che
non segue le gerarchie e sono inserite nel suo calcolo anche
gli indirizzi IP, che in realtà fanno parte del livello 3 (IP).
DESCRIZIONE
È la routine che compone un pacchetto TCP compilando
la struttura tcp contenuta
Funzione in_cksum
PROTOTIPO
unsigned short in_cksum(unsigned short *addr,int len)
89
Esempi pratici
INPUT
addr
struttura su cui eseguire il checksu
len
lunghezza di tale struttura
OUTPUT
answer
checksum
DESCRIZIONE
È la routine che contiene l'algoritmo per il calcolo del
cheksum sui pacchetti TCP/IP. Questo algoritmo viene usato
per scoprire errori generati da errori di memoria all'interno
dei router. Per prima cosa il campo checksum viene posto a 0
e il campo dati viene completato con uno 0 addizionale se la
sua lunghezza è un numero dispari poi viene eseguito
l'algoritmo che consiste nel sommare tutte le parole di 16 bit
che arrivano usando l'aritmetica del complemento a 1 e quindi
prendendo il complemento a 1 del risultato. Questo algoritmo
del checksum è più potente e da quindi maggiore affidabilità
del normale checksum.
4.6
PGP
PGP (Pretty Good Privacy) è un programma di crittografia
a chiave pubblica, che è diventato lo uno standard per l’utilizzo
della crittografia nella posta elettronica.
Esso si avvale dell’algoritmo RSA (descritto in
precedenza) per crittare i file.
Con PGP è possibile codificare un messaggio in modo che
solamente il destinatario possa leggerlo ma non una terza
persona. Inoltre, è possibile autenticare il mittente ed il
messaggio.
Questo risponde all’esigenza fondamentale di riservatezza
e sicurezza della corrispondenza privata.
La corrispondenza per posta elettronica ha da un lato
innumerevoli vantaggi ma presenta intrinsecamente un basso
grado di sicurezza. Ė infatti molto semplice per una terza
persona andare a leggere messaggi privati destinati ad altri,
oppure alterare un messaggio inviato da un altro, oppure ancora
inviarne uno con il nome di un altro.
L’utilizzo di PGP nella crittografia a chiave pubblica
Il problema storico della crittografia classica si può
riassumere in questo modo : per cifrare un messaggio si deve
utilizzare una chiave (segreta) con cui effettuare la cifratura.
La stessa chiave deve essere usata per decodificare il
messaggio cifrato.
Se ‘A’ vuole inviare il messaggio codificato al destinatario
‘B’, ha il problema di fare avere a quest’ultimo la chiave segreta
con la quale egli potrà decodificare il messaggio.
90
Esempi pratici
Se però ‘B’ sta all’altro capo del mondo e non c’è un
canale sicuro per trasmettere la chiave, questo sistema non può
funzionare, perché la chiave può essere intercettata.
Per esempio, se io non voglio che un messaggio e-mail sia
letto da altri, sarebbe inutile codificarlo in modo convenzionale
e poi inviare la chiave usata per la codifica ancora per e-mail.
Il problema viene risolto brillantemente dalla crittografia a
chiave pubblica, alla cui base sta un’idea semplice e geniale.
Ogni utente genera, mediante una funzione di PGP, una
coppia di chiavi.
L’algoritmo matematico che effettua questa operazione è
tale che :
• un messaggio codificato con una chiave della coppia
può essere decodificato solo con l’altra chiave della
stessa coppia;
• non è materialmente possibile, data una chiave della
coppia, ricavare l'altra.
Ogni utente tiene per sé una chiave della propria coppia,
denominata chiave segreta, e diffonde il più possibile l’altra,
denominata chiave pubblica.
Questo risolve tutti i problemi posti sopra.
Privacy
‘A’ vuole inviare un messaggio a ‘B’, e codifica quel
messaggio usando la chiave pubblica di quest’ultimo.
Solo ‘B’, che ha la corrispondente chiave segreta, è in
grado di decodificare e leggere il messaggio.
Autenticazione del mittente
‘A’ codifica il suo messaggio con la propria chiave privata.
Chiunque, avendo accesso alla chiave pubblica di ‘A’, può
decodificare quel messaggio. Se la decodifica riesce, si è allora
sicuri che esso è stato scritto da ‘A’, l’unico a possedere la
corrispondente chiave segreta.
‘A’ ha posto la sua "firma" elettronica sul messaggio.
Autenticazione del mittente e del messaggio
Ė possibile autenticare, facendo un passo in più, oltre al
mittente anche il contenuto del messaggio.
‘A’ effettua un "hashing" del suo messaggio. Si tratta di
una funzione unidirezionale, che a partire da un certo messaggio
ricava un valore di lunghezza fissa, detto hash, che caratterizza
il messaggio: una sorta di "checksum". Se il messaggio viene
alterato, l'hash non corrisponde più.
‘A’ attacca allora in fondo al suo messaggio il
corrispondente hash. ‘A’ può codificare con la propria chiave
privata ("firmare") tutto l'insieme, oppure lasciare il messaggio
vero e proprio in chiaro e firmare solo l'hash.
Chiunque può decodificare l'insieme ricevuto o il solo
hash con la chiave pubblica di ‘A’, ed è così sicuro del fatto che
il messaggio proviene da quel mittente.
91
Esempi pratici
Se inoltre, una volta effettuata la decodifica, messaggio ed
hash si corrispondono, si è sicuri che nessuno dei due è stato
alterato in qualche maniera.
In pratica, la firma elettronica realizzata dal PGP effettua
sempre l'autenticazione sia del mittente sia del messaggio.
Essa ha dunque le stesse funzioni della firma ordinaria su
un documento cartaceo.
Trasmissione della chiave
Col sistema di crittografia a chiave pubblica non c’è, come
nella crittografia convenzionale, una sola chiave usata per
entrambe le funzioni di codifica e decodifica, e che deve essere
posseduta solo dal mittente e dal destinatario.
Pertanto non si pone il problema di dover trasmettere in
modo sicuro quella chiave.
Ogni utente deve semplicemente tenere al sicuro la propria
chiave segreta e può diffondere senza alcun problema la propria
chiave pubblica. Anzi, più questa viene diffusa e meglio è.
Il PGP consente di effettuare tutte queste funzioni
mediante semplici comandi. Ė possibile avere varie funzioni
insieme.
Due procedure comuni sono per esempio :
• la corrispondenza privata
firmare un messaggio e contemporaneamente
codificarlo per un certo destinatario;
• per i messaggi pubblici o privati
effettuare l'hash di un messaggio e firmarlo per
autenticarne il mittente ed il contenuto, ma
lasciando il messaggio stesso in chiaro; questa
procedura viene comunemente chiamata firma in
chiaro, ed è quello che io ho fatto per il presente
testo.
Il PGP utilizza in realtà una intera collezione di algoritmi,
tra i più sicuri ed internazionalmente conosciuti nel campo della
crittografia.
Allo scopo di illustrare il processo messo in atto da PGP,
supponiamo di partire da un messaggio che deve essere firmato e
codificato.
La sequenza delle operazioni è la seguente :
A. PGP applica l'algoritmo di hashing MD5 per generare
l'hash del messaggio, avente lunghezza fissa pari a 128
bit. L'hash viene attaccato al messaggio.
B. PGP applica l'algoritmo di compressione dati ZIP per
comprimere l'insieme messaggio più hash ottenuto in A.
C. PGP applica un algoritmo di generazione numeri casuali
per generare una sequenza di 128 bit casuali.
92
Esempi pratici
D. PGP applica l'algoritmo di crittografia convenzionale
IDEA per codificare il messaggio compresso ottenuto
in B, usando come chiave ("session key") il numero
casuale generato in C.
E. PGP applica l'algoritmo di crittografia a chiave
pubblica RSA per codificare la session key. Il risultato
viene attaccato al messaggio codificato ottenuto in D.
La crittografia convenzionale è molto più veloce di
quella a chiave pubblica. PGP unisce i vantaggi della
crittografia a chiave pubblica e la velocità di quella
convenzionale.
Il messaggio viene in realtà codificato convenzionalmente,
ed è la session key usata che viene codificata con l'algoritmo a
chiave pubblica.
PGP applica l'algoritmo ASCII Armor Radix-64 per
trasformare il messaggio ottenuto in E in modo che esso
contenga solo caratteri ASCII bassi.
Questo algoritmo trasforma ogni gruppo di tre bytes in un
gruppo di quattro bytes.
Il messaggio ottenuto in F è quello finale, che può essere
inviato per e-mail. Il destinatario esegue la sequenza inversa di
operazioni.
Gli algoritmi utilizzati da PGP sono considerati
assolutamente sicuri. Per esempio, l'algoritmo di crittografia a
chiave pubblica RSA si basa sul prodotto di due numeri primi.
Per poter ricavare una chiave privata dalla corrispondente
chiave pubblica occorrerebbe fattorizzare questo prodotto.
Nel caso di chiavi a 1024 bit, è stato stimato che una rete
di un milione di computers impiegherebbe 10^10 anni a risolvere
il problema, un tempo pari all'età dell'universo!
Poi, ci sarebbe ancora il problema di ricavare la pass
phrase.
E questo per una sola coppia di chiavi tra tutte quelle
esistenti al mondo.
Esempio pratico dell’utilizzo del PGP
La prima cosa da fare è installare il programma, lo si può
trovare su Internet ed è scaricabile gratuitamente (per scopi non
commerciali, su www.pgpi.com) .
Dopo aver scaricato il file .zip basta scompattarlo in una
directory a piacimento e settare il parametro path del DOS nel
modo seguente :
• SET PATH = C:\<dir>%PATH%
• SET TZ = C:\<dir>
93
Esempi pratici
La prossima operazione sarà la generazione delle chiavi.
Per generare la coppia di chiavi si utilizza il comando:
pgp -kg
PGP chiede di :
1. Scegliere la lunghezza delle chiavi.
Vengono proposte tre possibilità, delle quali la terza
genera chiavi di 1024 bit.
Con la versione internazionale 2.6.3i è possibile generare
chiavi della lunghezza di 2048 bit digitando appunto il numero
2048 invece di scegliere una delle tre alternative proposte.
La generazione di chiavi da 2048 bit, non è possibile su un
sistema particolarmente lento, in questo caso è preferibile
generare chiavi a 1024 bit.
Figura 4.9 : Creazione delle chiavi con PGP (passo 1).
Nell’esempio che stiamo effettuando è stata scelta una
chiave di 1024 bits.
2. Inserire la User ID
In questo passaggio verrà scelto lo "User Name", chiamato
anche "User ID".
Generalmente, si usa nome e cognome seguito
dall'indirizzo e-mail in parentesi angolari :
Castiglioni Marco <[email protected]>
(E' possibile assegnare alle chiavi più identificativi, cosa
che si fa quando si hanno più indirizzi e-mail, per esempio.)
Questo è ciò che viene anche suggerito a video dall’help di
PGP, ed è la cosa preferibile.
In alternativa, se è facile che il vostro indirizzo e-mail
cambi, per creare il vostro "User Name" potete far seguire il
vostro nome e cognome, anziché dall'indirizzo e-mail, da un
qualunque altro dato che vi identifichi.
94
Esempi pratici
3. Inserire l a pass phrase
E' molto importante, perché si tratta della frase d’accesso
che permette di utilizzare la chiave segreta, senza la pass phrase
la vostra chiave segreta è inutilizzabile.
E' una password estesa : può essere un testo molto lungo
contenente qualunque carattere.
Scegliete una frase lunga che non sia intuibile, ma deve
però trattarsi di una frase costruita in modo che sia facile da
ricordare.
Figura 4.10 : Creazione delle chiavi con PGP (passo 2).
4. Premere dei tasti casualmente
Dovranno essere premuti dei tasti in modo casuale. In
questo modo PGP, in base alla velocità di pressione dei tasti,
calcolerà un numero casuale di 504 bits.
Figura 4.11 : Creazione delle chiavi con PGP (passo 3).
95
Esempi pratici
Figura 4.12 : Creazione delle chiavi con PGP (passo 4).
A questo punto, PGP genera la vostra coppia di chiavi.
Esse saranno contenute nei file secring.pgp (secret ring)
per quella segreta, pubring.pgp (public ring) per quella pubblica.
In questa versione del PGP non è necessario firmare la
chiave pubblica poiché viene fatto direttamente con
l’inizializzazione della chiave. Nelle vecchie versioni bisogna
utilizzare il comando pgp –ks “ID” dove ID è l’identificativo
dell’utente, per esempio la User Name.
Per visualizzare le chiavi pubblica si utilizza il comando
pgp -kv, così facendo viene visualizzata la chiave il giorno della
sua creazione il tipo di chiave (numero di bit utilizzati) e l’user
id.
Figura 4.13 : Visualizzazione della chiave pubblica.
96
Esempi pratici
Utilizzando il comando pgp -ka “ID” <percorso> si può
vedere la chiave pubblica.
Figura 4.14 : Estrazione della chiave pubblica.
Di seguito è riportata la chiave pubblica.
Type Bits/KeyID
Date
User ID
pub 1024/B1B74DA1 2002/05/19 <[email protected]>
-----BEGIN PGP PUBLIC KEY BLOCK----Version: 2.6.3ia
mQCNAzznyGsAAAEEAPTc2A3d/TbAMJZww89t6Z/qiC/5asH
mH2qgnqnHOtdjUXg9KWAG8wb2a4S4gIbrhpHfy9OtVFxujNgdR
yQ5w8ayBDr6hO5v9gjO4+6qJKLavDqw7fpq0YsKOz++Ts7P4Zq
v9e5EtZHRmKSupR8Tb/7vF14BnVvn5ragcraxt02hAAURtA88Y2
FzdGlAbXNuLmNvbT6JAJUDBRA858hrtqBytrG3TaEBAb5oA/9
rFrqrd4Y62352MrgttlJgh+Ou8xuIG0/HYAoB+M0IlbVXE5vYY9
1RC6KQsTYVgpv/sOd1/flDZMKokDoRq6IElKE3w7EHHn/r3A
CRAYfk9hTkc6PPq0P2IKZ1JzZJHVpslOct9EVtaIwXrClsQXb0K
LbM0FG9g7TpenLgoksKdg===zMPX
-----END PGP PUBLIC KEY BLOCK----Dopo di che è possibile crittare e decrittare un file di
testo. Il comando da utilizzare per crittare il testo è :
pgp –esta C:\percoso
•
•
Se si omette l'opzione "s" (sign), quindi digitate
-eta, il file viene codificato, ma non firmato.
Se si omette l'opzione "e" (encrypt), quindi digitate
-sta, il file viene firmato in chiaro, ma non
codificato.
97
Esempi pratici
Non è detto che il file da codificare e/o firmare sia un
testo, bensì può essere indifferentemente un file binario
qualunque.
PGP chiede in ogni caso di digitare la vostra pass phrase,
in modo da poter utilizzare la vostra chiave segreta.
Ė importante che il comando per codificare e/o firmare
(nonché quello per estrarre la vostra chiave pubblica) contenga
sempre l'opzione "a" (ASCII Armor), come si vede dal comando
riportato sopra.
Questo perché quando si invia un file per e-mail, esso
passa attraverso e arriva su sistemi di tipo molto diverso.
Qualunque sistema però è in grado di riconoscere e
trattare caratteri ASCII il cui codice decimale è compreso tra 0 e
127 (il cosiddetto ASCII basso). Perciò è indispensabile che un
file inviato per e-mail sia formato esclusivamente da tali
caratteri (file ASCII armored o semplicemente ASCII), e non da
caratteri qualsiasi. PGP trasforma, mediante l’opzione "a", il file
prodotto in modo che sia ASCII armored.
Figura 4.15 : Crittazione di un file (passo 1).
Dopo di che il PGP chiederà di riscrivere la vostra
password segreta, in seguito viene anche chiesto l’user ID, dopo
di che verrà creato il file crittato.
98
Esempi pratici
Figura 4.16 : Crittazione di un file (passo 2).
Il file di testo crittato è il seguente:
-----BEGIN PGP MESSAGE----Version: 2.6.3ia
hIwDtqBytrG3TaEBA/42ma+Cg8giyBNS5hA31/2LHgp8xj0EHv4
PUrFuwlYc4jNCdTQUklqHdhkLh8WSIzx12ps7ucjs18H4+Mn1vY
qOKp4W1pt5OxZ5gD8V0yrFOnhkWzxA+59acHgUAcuLARmTU
gflkmSdDtfaWLKR+ojHDJt8rvevfaroIT2WQsejLKYAAAE3ixIbp
Is10lfjG2Re3XRXKRzwHd/bhpFZIjcU5jv3gJtTnMb8gdj3Kscv8N
UG+l1W2DKNVuCWryoN7+8llHOn9xERkTa5VdnMjaI9jnmgd4c
cOZjaTFonmJEXVkKUGFlH1DasvsHriezxzcsRobg0y1SWl4yHc0
kbkDTEWfgz+GJQO9d+GOy19sxUXy6v/Hi7dQEXr0PhOjBfmx
LW1+3U76ZIejzfX/fr7cPUU4Kin2qv85PUZ5AJMZMLLSVNO3
ObOFqTeweanlaYUTPagFL5IdAC6yU5eZ4eCa/1djFh27IkIxqXIE
b2o+LpvRklKwVlSxJ2sXb/BayQbrHOM5gw0QsyZOhj+CP9NOt
MXD9vsPk+Z526h5l2uU86yapABeJTu7YZBdhgRVAq5KqHYdG
WfdLinPWvtK0==qHft
-----END PGP MESSAGE----Per decodificare il file si dovrà utilizzare il seguente
comando:
pgp C:\percoso
99
Esempi pratici
Figura 4.17 : Decrittazione di un file.
Dopo questa operazione il file viene decodificato e il testo
può comparire in chiaro.
Qui sotto il testo è riportato in chiaro:
Questa è la mia area di progetto questo è un file di testo
fatto per provare il programma che critta e decritta i messaggi di
posta elettronica PGP!
Questo comando ha molteplici funzioni, perché agisce
indifferentemente su codifica e firma.
Se il messaggio di partenza era codificato, il comando
citato lo decodifica.
Se in aggiunta esso era anche firmato, il comando verifica
inoltre la firma (e quindi l’autenticità del mittente e del
messaggio stesso).
Se era solo firmato, viene semplicemente verificata la
firma.
100
Conclusioni
CONCLUSIONI
Dr. M : “Che difficoltà avete incontrato nello sviluppare
l’area di progetto?”
Pozzetti : “La difficoltà maggiore incontrata è stata lo sviluppo
del DES. La manipolazione bit per bit usata dal DES
rendeva più adatto lo sviluppo dell’algoritmo in
Assembler.”
Castiglioni : “Per quanto riguarda la parte storica riguardante
la seconda guerra mondiale non ci sono stati
problemi, mentre per quanto riguarda la parte
della storia della crittografia ho incontrato alcuni
problemi: a causa dell’abbondanza di informazioni
si è dovuto estrapolare solo lo stretto necessario.
Nella prova pratica con il PGP le difficoltà
incontrate riguardano l’applicazione delle
istruzioni, infatti alcune di esse riportate nell’help
erano errate.”
Trevisan : “Ho incontrato difficoltà nel programma in Linux,
legatiall’uso dei socket raw. Studiando la crittografia
di Outlook Express non è stato possibile verificare
con esempi pratici l’utilizzo della firma elettronica e
degli algoritmi crittografici, poiché non si disponeva
di un ID digitale.”
Dr. M : “Cosa avete imparato di nuovo durante lo sviluppo
dell’area di progetto?”
Pozzetti. : “Per quanto riguarda la programmazione ho imparato
a programmare utilizzando Visual C++, in
particolare è stato utile l’uso di Winsock. Nel campo
della crittografia sono venuto a conoscenza degli
algoritmi più usati quali il DES e l’RSA e alcune
delle tecniche che nel futuro renderanno sempre più
sicura la comunicazione via Internet.”
Castiglioni: “Nella parte storica, ho scoperto quando è nata
la crittografia e l’utilità che è riuscita a
conquistarsi nel corso degli anni e dei secoli.
Per quanto riguarda la parte applicativa, ho
lavorato con il programma PGP, che permette la
codifica e decodifica dei messaggi.
Mi è servito per vedere praticamente e non solo
teoricamente come funziona un programma per la
crittografia.”
Trevisan : “Ho approfondito il protocollo TCP/IP, sia
teoricamente sia praticamente, costruendo un
programma che simulasse una trama TCP/IP.”
Dr. M : “Come ampliereste la vostra area di progetto?”
Pozzetti. : “Nella parte crittografica sono state tralasciate
importanti parti, come la simulazione delle macchine
cifranti usate durante la seconda guerra mondiale,
101
Conclusioni
oppure lo studio più approfondito di alcuni
algoritmi come l’RSA, trattato solo marginalmente.
In particolare mi sarebbe piaciuto realizzare una
simulazione della macchina Enigma e della Bomba di
Turing per rendere meglio l’idea del lavoro
effettuato dagli Alleati e dal’Asse nello sviluppo dell
crittografia.”
Trevisan : “Nella parte della sicurezza sarebbe stato utile
approfondire ulteriormente i metodi di attacco degli
hacker, poiché solamente in questo modo si possono
migliorare i metodi realativi alla sicurezza. D’altra
parte era impossibile trattare tutti gli argomenti in
modo dettagliato, poiché l’area di progetto
comprendeva argomenti ampio raggio.”
Castiglioni: “Vorrei aggiungere ancora delle parti sulla storia
della crittografia, sulla utilità che ha avuto nella
seconda guerra mondaile e che sta avendo tuttora
in internet.
Vorrei applicare il PGP, nella posta elettronica,
anche se è difficile ottenere il permesso dalla
autorità competenti.”
Dr. M : “Qual è stata la fonte primaria di informazioni?”
C., P., T. : “Internet e relativi manuali.”
Dr. M : “Ognuno commenti il lavoro altrui.”
Pozzetti. : “Il lavoro svolto da Castiglioni relativo alla storia e
alle basi della crittografia è stato veramente
impegnativo, soprattutto la ricerca di materiale è
stata difficoltosa. Alla fine ci si è ritrovati con più
informazioni di quante ne servissero. Inoltre la sua
parte di lavoro mi è servita per comprendere meglio
il funzionamento di alcuni algoritmi crittografici,
permettendomi di implementarne alcuni nelle
applicazioni sviluppate.
Il lavoro di Trevisan è stata la base per lo sviluppo
dell’applicazione di scambio per i messaggi crittati,
che è stata integrata con il DES.”
Castiglioni: “ La parte svolta da Trevisan è stata molto utile
per capire come avviene lo scambio dei messaggi
crittati tra due utenti.
Il lavoro di Pozzetti è stato importatntissimo,
poiché grazie ad esso, si può vedere come vengono
crittati i messaggi con l’algoritmo DES, è stato un
lavoro molto lungo e complesso, ma che è stato
svolto con molta professionalità.”
Trevisan : “Entrambi le altri parti sono state molto complete; la
102
Conclusioni
parte di Pozzetti, che comprendeva principalmente
la crittografia, è stata molto complessa ed è stata
svolta in modo particolareggiato e professionale;
Castiglioni è stato molto preciso e particolareggiato
nella parte storica, mentre la sua descrizione
riguardante il PGP è stata utile ad un suo utilizzo
pratico.”
Dr. M : “Come è stato lavorare in gruppo?”
Pozzetti. : “Lavorando in gruppo la cosa più importante da
tenere in conto è la divisione del lavoro. Se il lavoro
viene diviso in maniera esatta all’ora il tutto fila via
liscio, altrimenti, ci si ritrova a sprecare tempo,
tralasciando alcune parti che alla fine ci si ritroverà
ad affrontare con l’acqua alla gola.
Un’altra cosa estremamente importante è avere già in
mente il flusso del lavoro, ovvero conoscere
precisamente gli argomenti da affrontare, in modo da
non ritrovarsi a metà dello sviluppo con un’idea che
non coincide per nulla con quello che si aveva in
mente all’inizio.”
Castiglioni: “ E’ stata un’esperienza molto utile, ci ha fatto
capire cosa vuol dire lavorare in gruppo.
Con il lavoro di gruppo ci si può confrontare, si
chiedere aiuto ai propri compagni, che ti sanno
aiutare e consigliare. Ed è molto gratificante
mettere a disposizione le proprie conoscenze per
la buona riuscita del lavoro.”
Trevisan : “E’ stata un’esperienza stimolante, poiché si impara
a comunicare con gli altri per suddividere il lavoro e
proporre le proprie idee.”
Dr. M : “Che conclusioni avete tratto dallo sviluppo dell’area di
progetto?”
Pozzetti. : “Personalmente credo che il mondo della crittografia
sia molto affascinante, sia per quanto riguarda il lato
“buono” sia per quanto riguarda il lato “cattivo”.
Purtroppo la crittoanalisi (lato “cattivo”) non è stata
affrontata nel modo che meritava, lasciando un po’
di amaro in bocca.
La stessa affermazione può valere per le
comunicazione via socket. Gli argomenti trattati in
questo campo sono stati veramente pochi,
soprattutto a causa del poco tempo a disposizione.”
Castiglioni: “Dall’analisi che abbiamo fatto sulla crittografia, si
può dire che essa prenderà sempre più parte nel
mondo di internet, questo per avere una maggiore
sicurezza, che permetterà di scambiare
informazioni o di compiere transazioni in tutta
sicurezza.”
Trevisan : “Penso che analizzando la sicurezza informatica, si
103
Conclusioni
possa notare che sia un campo in continua
espansione e sviluppo. Quindi è molto difficile
essere aggiornati, ma risulta interessante e
stimolante.”
Dr. M : “Definite con poche parole la vostra area di progetto.”
Pozzetti. : “Una base per chi vuole incominciare a conoscere il
mondo della crittografia.”
Castiglioni: “Può essere una base per chi si vuole avvicinare
al mondo della crittografia e un aiuto per chi si è
già avvicinato alla crittografia e ne vuole sapere di
più.
Trevisan : “L’area di progetto è stata sviluppata in varie parti:
storico, gestione di rete e crittografia. Alla parte
teorica si affianca una parte di programmazione in
vari linguaggi. L’argomento pur risultando molto
ampio e complesso è stato cercato di essere trattato
in modo completo.”
104
Appendice A
Appendice A
SSL
1
2
Cos’è l’SSL
Creazione di una connessione SSL
1 Cos’è l’SSL
SSL (Secure Socket Layer protocol) è un protocollo aperto
e non proprietario; è stato sottoposto da Netscape
Communications all'Engineering Task Force per la sua
standardizzazione, anche se di fatto è stato accettato come uno
standard da tutta la comunità di Internet ancor prima del
verdetto dell'IETF. La versione 3.0 del protocollo rilasciata nel
novembre 1996, è un'evoluzione della precedente versione del
1994 la SSL v2.0, e rappresenta al momento una delle soluzioni
più utilizzate per lo scambio di informazioni cifrate. Tale
evoluzione introduce un livello di sicurezza superiore rispetto
alla precedente grazie ad una maggiore attenzione nella fase di
autenticazione tra client e server. Il futuro di SSL è
rappresentato dal protocollo TLS v1 (SSL v3.1) sottoposto a
standardizzazione nel novembre 1998.
Il protocollo SSL è nato al fine di garantire la privacy
delle comunicazioni su Internet, infatti permette alle
applicazioni client/server di comunicare in modo da prevenire le
intrusioni, le manomissioni e le falsificazioni dei messaggi. Il
protocollo SSL garantisce la sicurezza del collegamento
mediante tre funzionalità fondamentali :
• privatezza del collegamento: per assicurare un
collegamento sicuro tra due utenti coinvolti in una
comunicazione, i dati vengono protetti utilizzando
algoritmi di crittografia a chiave simmetrica (ad es.
DES, RC4, ecc.);
• autenticazione: l'autenticazione dell'identità nelle
connessioni può essere eseguita usando la
crittografia a chiave pubblica (per es. RSA, DSS
ecc.). In questo modo i client sono sicuri di
comunicare con il server corretto, prevenendo
eventuali interposizioni. Inoltre è prevista la
certificazione sia del server che del client;
• affidabilità: il livello di trasporto include un
controllo sull'integrità del messaggio basato su un
apposito MAC (Message Authentication Code) che
utilizza funzioni hash sicure (per es. SHA, MD5
ecc.). In tal modo si verifica che i dati spediti tra
client e server non siano stati alterati durante la
trasmissione.
105
Appendice A
Il protocollo SSL è composto da :
• protocollo SSL handshake, permette al server ed al
client di autenticarsi a vicenda e di negoziare un
algoritmo di crittografia e le relative chiavi prima
che il livello di applicazione trasmetta o riceva il suo
primo byte. Un vantaggio di SSL è la sua
indipendenza dal protocollo di applicazione, in tal
modo un protocollo di livello più alto può
interfacciarsi sul protocollo SSL in modo
trasparente;
• protocollo SSL record, è interfacciato su di un
protocollo di trasporto affidabile come il TCP.
Questo protocollo è usato per l'incapsulamento dei
dati provenienti dai protocolli superiori.
Figura 1 : SSL è un
protocollo a due strati, SSL
Record a livello inferiore ed
SSL Handshake a livello
superiore, che si interfaccia
con una applicazione ad
esempio HTTP.
2 Creazione di una connessione SSL
SSL prevede una fase iniziale, detta di handshake, usata
per iniziare una connessione TCP/IP. In particolare il risultato
di tale fase è l'avvio di una nuova sessione che permette la
contrattazione da parte del client e del server del livello di
sicurezza da usare ed il completamento delle autenticazioni
necessarie alla connessione. Quindi SSL procede con la cifratura
(e/o con la messa in chiaro) della sequenza di byte del
protocollo applicazione usato, ad esempio nell'HTTP tutte le
informazioni sia di richiesta che di risposta sono completamente
cifrate, incluso l'URL richiesto dal client, qualsiasi contenuto di
form compilati (quindi anche eventuali numeri di carte di
credito...), ogni informazione sulle autorizzazioni all'accesso
come username e password, e tutti i dati inviati in risposta dal
server al client.
Il protocollo SSL usa una combinazione di chiavi
pubbliche e chiavi simmetriche. La cifratura a chiave simmetrica
è molto più veloce della cifratura a chiave pubblica, anche se
quest'ultima provvede ad una tecnica di autenticazione migliore.
Una sessione SSL inizia sempre con uno scambio di messaggi
chiamati di SSL handshake. L'handshake consente al server di
autenticarsi al client usando una tecnica a chiave pubblica,
quindi permette al client ed al server di cooperare per la
106
Appendice A
creazione delle chiavi simmetriche usate per una veloce
cifratura, decifratura e controllo delle intrusione durante la
sessione avviata. Eventualmente, l'handshake permette anche al
client di autenticarsi al server.
Nel protocollo SSL Handshake l'avvio di una nuova connessione
può avvenire o da parte del client o da parte del server. Se è il
client ad iniziare, allora questo invierà un messaggio di client
hello, iniziando così la fase di Hello, e si porrà in attesa della
risposta del server che avviene con un messaggio di server hello.
Nel caso in cui sia il server ad iniziare la connessione, questo
invierà un messaggio di hello request per richiedere al client di
iniziare la fase di Hello. Con lo scambio di questi messaggi, il
client ed il server si accorderanno sugli algoritmi da usare per la
generazione delle chiavi; in particolare il client ne proporrà una
lista, quindi sarà il server a decidere quale di essi dovrà essere
utilizzato.
A questo punto può iniziare o meno, a seconda del metodo di
autenticazione impiegato (autenticazione di entrambe le parti,
autenticazione del server con client non autenticato, totale
anonimato), uno scambio di certificati tra client e server.
L'autenticazione è un controllo che si può effettuare per provare
l'identità di un client o di un server. Un client abilitato può
controllare che il certificato del server sia valido e che sia stato
firmato da un'autorità fidata. Questa conferma può essere utile,
per esempio, se un utente invia il numero di carta di credito e
vuole controllare l'identità del ricevente.
Allo stesso modo un client può essere autenticato, questo
potrebbe essere utile se il server è ad esempio una banca che
deve inviare dati finanziari confidenziali ad un suo cliente che
necessita quindi di essere autenticato.
E' importante notare che sia l'autenticazione del client che
quella del server implica la cifratura di alcuni dati condivisi con
una chiave pubblica o privata e la decifratura con la chiave
corrispondente. Nel caso dell'autenticazione del server, il client
deve cifrare dei dati segreti con la chiave pubblica del server.
Solo la corrispondente chiave privata può correttamente
decifrare il segreto, così il client ha delle assicurazioni sulla
reale identità del server poichè solo lui può possedere tale
chiave. Altrimenti il server non potrà generare le chiavi
simmetriche richieste per la sessione, che verrà così terminata.
In caso di autenticazione del client, questi deve cifrare alcuni
valori casuali condivisi con la sua chiave privata, creando in
pratica una firma. La chiave pubblica nel certificato del client
può facilmente convalidare tale firma se il certificato è
autentico, in caso contario la sessione verrà terminata.
Avvenuta l'autenticazione si procede con la generazione delle
chiavi per la cifratura e per l'autenticazione dei dati provenienti
dal livello di applicazione, tutto questo attraverso i messaggi di
server key exchange e client key exchange. Terminata questa
operazione, il server annuncerà la fine della fase di Hello al
client, con l'invio di un messaggio di server hello done, dopodichè
con l'invio di un messaggio di change CipherSpec entrambi
107
Appendice A
controlleranno la correttezza dei dati ricevuti e se tutto è
avvenuto in maniera corretta, da questo punto in poi useranno
gli algoritmi di sicurezza concordati. La fase di handshake
terminerà con l'invio, da entrambe le parti, di un messaggio di
finished che sarà il primo dato ad essere cifrato.
108
Appendice B
Appendice B
La firma digitale
1
2
3
Lo standard DSS e l’algoritmo DSA
Protocolli di sicurezza
Sistemi di autenticazione
1 Lo standard DSS e l’algoritmo DSA
Il National Institute of Standards and Technology (NIST)
ha pubblicato il Digital Signature Algorithm (DSA) nell'ambito
del Digital Signature Standard (DSS) che è parte del progetto
Capstone attuato dal Governo degli Stati Uniti. DSS è stato
scelto nel maggio 1994 dal NIST in collaborazione con l' NSA
come standard di firma digitale del Governo degli USA. DSA è
basato sul problema dei logaritmi discreti ed è in relazione con
gli schemi di firma proposti da Schnorr ed El Gamal. DSA può
essere utilizzato soltanto per la firma digitale contrariamente ad
RSA, utilizzabile sia per la digital signature che per la codifica e
la privacy. Nel DSA la generazione della firma è più veloce della
verifica della stessa, mentre con RSA la verifica è sensibilmente
più veloce della generazione, per via delle diverse dimensioni
degli esponenti pubblico e privato. La scelta di rendere più
veloce la fase di firma o la fase di verifica può essere oggetto di
discussione e di studio, come si può apprezzare nei lavori di
Wiener e Naccache che hanno cercato dei compromessi per
equilibrare la velocità delle due fasi ed hanno esplorato le
possibilità di miglioramento dell'efficienza di DSA. Anche se
molti degli aspetti peculiari di RSA sono stati criticati sin dal
momento del suo annuncio, esso è stato incorporato in un
grande numero di sistemi. Le critiche mosse inizialmente si
focalizzavano su pochi argomenti principali: mancava la
flessibilità dell' algoritmo RSA; la verifica delle firme era troppo
lenta; l'esistenza di un algoritmo diverso dallo standard RSA
poteva influenzare negativamente il mercato; il procedimento
per cui il NIST sceglieva DSA era poco chiaro, arbitrario e
fortemente influenzato dall' NSA.
Un altro argomento scottante è quello della sicurezza
dell'algoritmo. Originariamente proposto dal NIST con una
chiave fissa di 512 bits, dopo molte critiche per l' eventuale
mancanza di sicurezza a lungo termine, dovuta alla lunghezza
troppo ridotta della chiave, il NIST ha rivisto lo standard DSS
ed ha introdotto chiavi della lunghezza di 1024 bits. Oggi DSA è
considerato sicuro con chiavi di 1024 bits. Al giorno d' oggi non
si conoscono attacchi efficienti portati al problema dei logaritmi
discreti, che sorregge lo schema crittografico di DSA.
109
Appendice B
2 Protocolli di sicurezza
Molti protocolli sono stati realizzati per la sicurezza delle
comunicazioni via Internet, alcuni dei quali sono :
• S/MIME
S/MIME (Secure / Multipurpose Internet Mail Extensions)
è un protocollo che aggiunge firma digitale e cifratura ai
messaggi standard MIME. MIME è lo standard proposto per la
posta elettronica avanzata. I messaggi di posta elettronica
consistono di due parti : un’intestazione, che contiene
informazioni vitali per la spedizione del messaggio e un corpo,
che non ha nessun formato particolare, a meno che il messaggio
non sia nel formato MIME. Questo formato, infatti, fornisce una
struttura anche al corpo, ed è quindi possibile inviare testo,
audio, immagini ed altri elementi multimediali. Lo standard
MIME da solo non è in grado di fornire una sicurezza
sufficiente all' utente e quindi si è creato il protocollo S/MIME
che quindi cripta il corpo della mail rendendola indecifrabile a
terzi.
• S/WA
La S/WAN (Secure Wide Area Network) è un' iniziativa
nata per promuovere lo sviluppo e la diffusione delle VPNs
Virtual Private Networks basate su Internet e su protocollo IP.
Questo risultato è ottenuto adottando lo standard IP/Sec,
l'architettura di sicurezza del protocollo IP. In questo modo si
può garantire l'interoperabilità con firewall e prodotti basati su
protocolli TCP/IP. S/WAN supporta la codifica a livello di
protocollo IP, per cui può fornire una sicurezza più a bsso
livello rispetto a protocolli quali SSL. S/WAN utilizza
l'algoritmo RC5 con chiavi della lunghezza compresa tra 40 e
128 bits.
• IP/Sec
Il gruppo di lavoro IP Security Protocol (IP/Sec), facente
parte dell' Internet Engineering Task Force (IETF), sta
definendo un insieme di specifiche per l' autenticazione basata
sulla crittografia per introdurre un alto livello di sicurezza e
segretezza al livello di trasmissione datagram su Internet. I
risultati di queste specifiche comprenderanno un elevato livello
di sicurezza delle trasmissioni host-to-host, tunnels incapsulati e
la definizione di Virtual Public Networks (VPNs) che
fornirannosicurezza ai protocolli residenti ai livelli superiori
rispetto al protocollo IP. I formati dei protocolli per l' IP/Sec
Authentication Header (AH) e per IP Encapsulating Security
Payload (ESP) sono indipendenti dall'algoritmo di codifica
adottato, permettendo quindi una larga interoperabilità.
110
Appendice B
3 Sistemi di autenticazione
In un ambiente di rete in cui molti utenti vogliono
comunicare reciprocamente sono necessari dei protocolli che
garantiscano sicurezza, riservatezza, trasparenza e velocità nelle
transazioni. Di seguito sono presentate le soluzioni più usate
oggigiorno :
• SSH
SSH (Secure Shell) è un programma che permette di
connettersi ad un altro computer attraverso una rete, eseguire
comandi su una macchina remota e spostare files da una
macchina all'altra il tutto in maniera sicura. Fornisce solide
autenticazioni e comunicazioni sicure su canali insicuri. Può
essere visto come un rimpiazzo delle istruzioni rlogin, rsh, e
rcp. SSH gestisce connessioni di tipo X sicure e si interfaccia a
connessioni TCP già esistenti.
Protezioni fornite da SSH
1. 'IP spoofing' (truffa dell'IP) : quando un host
remoto vuole spedire pacchetti verso un host
autenticato, SSH protegge contro truffatori che,
sulla rete locale, pretendano di essere i router verso
l'esterno;
2. 'IP source routing' : un host può pretendere che un
pacchetto IP arrivi da un host autenticato e ciò deve
essere garantito da SSH;
3. 'DNS spoofing ': un hacker tenta di forzare i record
del name server;
4. Intercettazione di password in chiaro e altri dati non
crittati da parte di host intermedi;
5. Manipolazione dei dati da parte di persone che
possiedono il controllo di host intermedi;
6. Attacchi basati sull'ascolto di autenticazioni X e
sull'utilizzo successivo di queste ultime per ottenere
false connessioni al server X11.
Protezioni non garantite da SSH
SSH non dà aiuto a fronte di attacchi alla sicurezza del
proprio host di altro genere. Così, se un hacker ha ottenuto
l'accesso alla root della macchina, può sovvertire lo stesso SSH.
Se qualcuno ha accesso alla nostra home directory, la sicurezza
diventa inesistente. Questo può accadere nel caso in cui la
nostra home directory venga esportata via NFS.
Tutte le comunicazioni di SSH usano IDEA o uno degli
altri protocolli simmetrici (three-key triple-DES, DES,
Blowfish). Le chiavi segrete vengono scambiate usando RSA, e i
dati relativi alle chiavi scambiate vengono distrutti ogni ora (le
chiavi non vengono salvate da nessuna parte). Ogni host ha la
propria chiave RSA che viene usata per autenticare l'host stesso
111
Appendice B
(quando si usa un'autenticazione tipo RSA). La codifica è usata
come protezione contro l'IP spoofing; l'autenticazione a chiave
pubblica è usata a fronte del DNS e del routing spoofing.
• NIS+
NIS+ Overview : NIS+, acronimo di Network Information
Service, e' un'evoluzione del servizio NIS entrambi trademark di
Sun Microsystems (quest'ultimo nome sostitui' l'originale YP
(Yellow Pages) per ragioni di copyright).
L'obiettivo di NIS era diminuire l'insieme di informazioni (di
uno stesso cluster) replicate su piu' host, propagandole
sottoforma di tabelle, in modo da ottenere una gestione
centralizzata dei dati. NIS+ evolve questo concetto aggiungendo
un meccanismo di autorizzazzione e autenticazione per tutti i
client richiedenti tali informazioni. La prima differenza tra i due
tipi di servizio e' l'organizzazione dell'insieme di informazioni
riguardanti macchine e utenti, indicato col nome di "namespace"
"flat" con NIS e "hierarchical" con NIS+.
Il namespace puo' essere visto come un albero la cui radice ha
due foglie ed eventuali rami ad ognuno dei quali e' attaccato un nodo
figlio. Ogni nodo figlio (compresa la radice) ha due foglie costituite
da due sottodirectory virtuali chiamate "groups_dir" e "org_dir"; la
prima contiene eventuali sottogruppi NIS+ e la seconda varie tabelle.
Secondo la definizione un "NIS+ domain" e' l'insieme del nodo figlio
(sia radice o semplice nodo interno), delle due sottodirectory e delle
tabelle. NIS+ rende possibile la creazione di suddivisioni tra loro
indipendenti del namespace, riferiti di solito col nome di
"subddomain".
NIS+ Security : l'accesso al namespace e': consentito ai "NIS+
principals", fatto rispettare dai "NIS+ servers" e soggetto ai
permessi di ciascun object. Un NIS+ principal e' un utente o una
macchina le cui credenziali sono presenti nel namespace.
Quando un client (utente o macchina) manda una richiesta al
server, vi inserisce automaticamente le credenziali di NIS+ principal.
Il server a sua volta accodera' tale richiesta in una delle due
categorie: autenticata o non utenticata, rispettivamente per le
richieste generate da principal per i quali il server ne riconosce
l'identita', e per le quali il server non riesce (client qualsiasi).
L'accesso ad un NIS+ object differisce a seconda della coda in
cui si trova la richiesta ed avviene in base ai permessi associati alle
quattro azioni possibili divise per categorie. Ognuna di queste
categorie specifica una "authorization category" differente. Per le
richieste nella prima coda si hanno le categorie Owner, Group e
World, mentre per quelle nella seconda la Nobody. I possibili
permessi in ogni categoria sono quattro e indicano rispettivamente la
possibilita' di leggere (r), modificare (m), creare (c) e distruggere (d)
un oggetto; tutto cio' in perfetta similitudine con quanto avviene per
il meccanismo di accesso ai file nel sistema operativo UNIX.
Si noti che oltre ai permessi propri di ogni oggetto (facenti parte
della sua definizione) e' anche possibile specificare altri permessi per
ogni colonna o entry di una tabella NIS+ (con alcune limitazioni).
112
Appendice B
• Kerberos Authentication System
Kerberos e' un servizio di autenticazione distribuito il cui
compito è permettere ad utenti di workstations l'accesso alle
risorse di rete in modo sicuro. Kerberos deve dunque gestire i
permessi dei vari user inibendo la possibilità che qualcuno riesca
a spacciarsi per qualcun'altro.
Kerberos appartiene alla categoria "authentication for real
- time" intendendo con questo termine che il processo client
rimane in attesa di una risposta in modo da poter dare i risultati
all'utente, questo implica una rapida risoluzione del problema di
autenticazione per evitare lunghe attese. Applicazioni che
richiedono questo tipo di autenticazione sono : rlogin, file
system r/w, information retrieval su Web etc.
Kerberos fu sviluppato a meta' degli anni 80 come parte
del progetto Athena al MIT ma succesivamente furono
necessarie delle modifiche per supportare nuove politiche e
metodi di utilizzo, attualmente e in fase di sviluppo la versione
5 (V5) che viene considerata essere il "Kerberos standard" anche
se la V4 viene utilizzata in molti siti nel mondo.
Essenzialmente Kerberos si basa sull'utilizzo di chiavi per
criptare le informazioni scambiate tra le entita' che partecipano
al protocollo di autenticazione. Il metodo di crittografia
utlizzato da Kerberos V4 e' il DES (Data Encryption Standard)
che ha la caratteristica di avere la stessa chiave sia per
codificare che per decodificare.
113
Appendice C
Appendice C
Crittografia quantica
1
2
Fondamenti sui quanti e sui fotoni
Crittografia quantica
1 Fondamenti sui quanti e sui fotoni
Prima di iniziare a parlare della crittografia quantica è
meglio precisare il termine "quanto" : un osservatore attento
può notare che il termine più vicino alla parola quanto è
quantità. All'inizio del secolo i fisici hanno notato che c'era
qualcosa di sbagliato nella teorica classica, per essere più
precisi, essi hanno notato che la loro prospettiva delle particelle
fondamentali non coincideva con quella rilevata dagli
esperimenti fatti. La conclusione logica fu che c'era qualcosa di
errato nella classica concezione di atomo. Max Planck introdusse
per primo un nuovo approcio al problema. Nella fisica classica,
gli elettroni orbitano attorno al nucleo dell'atomo e possono
avere una qualsiasi energia e di conseguenza orbitare a qualsiasi
distanza da esso.
Il problema che generò questa idea è che l'elettrone,
carico negativamente e il nucleo (composto da protoni, carica
positiva e neutroni, carica neutra) carico positivamente,
potessero collassare. Più precisamente si credette che l'elettrone
avrebbe potuto collassare nel nucleo per circa 0.0000000001
secondi, a causa delle cariche opposte assunte da elettrone e
nucleo.
La risposta fu che l'elettrone non avrebbe potuto avere
qualsiasi energia mentre orbita attorno al nucleo. L'energia
dell'elettrone è il quanto. Questo significa che l'elettrone ha
un'energia strettamente definita e può orbitare solamente ad
alcune distanze dal nucleo. Per essere più precisi, tutto questo
non è propriamente vero, l'elettrone non orbita esattamente
nell'orbita, infatti l'orbita indica solamente il posto dove ci sono
più probabilità di localizzare l'elettrone.
Questo discorso ci porterà a parlare della meccanica
quantistica, in cui non si parla di certezza ma solamente di
possibilità.
Le regole espresse in precedenza sono chiamate leggi di
Heisenberg. Esse dicono che è impossibile determinare entrambe
le proprietà di un atomo allo stesso tempo, senza influenzare
una di esse.
Di seguito verranno enunciati alcuni principi di base della
meccanica quantistica.
114
Appendice C
Il fenomeno della materia è che essa è costituita da piccole
parti. La più piccola serve per costruire le altre costruzioni della
natura, come atomi e molecole, chiamate particelle
fondamentali. Quello che i fisici hanno trovato è che le
particelle non sono particelle nel senso di sfere, come si
potrebbe immaginare, ma esse sono sottoforma di onde.
Figura 1 : Esempio di particelle..
Adesso parleremo di polarizzazione e shift di fase.
Supponiamo di avere due onde della stessa lunghezza che
viaggiano sullo stesso percorso x. Cosa dire degli altri assi E e
B? Un'onda può avere gli assi B ed E alla stessa costante di 90°
e quindi può ruotare attorno ad essi.
Figura 2 : Esempio di polarizzazione.
Dando una posizione casuale a due vettori in un sistema di
assi, è possibile notare che essi appaiono più vicini, essendo
ruotati di 90°.
Dalla figura 2 è possibile dire che che l'onda elettro magnetica è polarizzata per 90°. Di conseguenza il fotone,
considerato la particella elementare della luce, può essere
polarizzato, perchè? Perchè, come accennato in precedenza, la
luce è sia particella che onda, e di conseguenza, ogni protone
può essere considerato anche come un'onda.
115
Appendice C
Ora rimane un ultimo termine da definire : shift di fase.
La figura sottostante descrive un'onda elettro - magnetica. Essa
è una funzione seno. Essa è periodica di 360°. Questo significa
che la funzione si ripete dopo alcuni valori di x.
Figura 3 : Esempio di phase shifting.
Dalla figura è possibile notare che le funzione verde e
rossa sono le stesse, ma shiftate sull'asse x. Per essere più
precisi la funzione rossa è sin(x), mentre quella verde è
sin(x+pi/4). Adesso si può dire che quest'ultima è shiftata di
fase pi/4 (45°). La stessa cosa succede per le onde
elettromagnetiche perchè esse sono descritte da un'onda
sinusoidale.
2 Crittografia quantica
Ora si hanno due possibilità per mandare un messaggio.
Un cifrario a chiave privata, come quello di Vernam, se è
possibile tenere segreta la chiave. E' proprio in questo punto
che entra in gioco la fisica quantistica.
Bob e Alice devono dividere una chiave segreta, la
crittografia quantistica permette a due parti separate fisicamente
di creare una chiave segreta casuale senza servirsi del servizio di
un corriere. La cosa migliore è che il sistema permette di
verificare se la chiave è stata intercettata. La crittografia
quantistica non è un sistema crittografico totalmente nuovo, ma
la procedura di distribuzione della chiave in perfetta discrezione
lo rende sicuro.
Per capire meglio come funziona la crittografia quantistica
possiamo considerare il protocollo di comunicazione BB84,
introdotto nel 1984 da Charles Bennett dell'IBM e Gilles
Brassard dell'Università di Montreal.
116
Appendice C
Alice e Bob sono connessi da un canale quantico e da da
un classico canale pubblico. Se i singoli fotoni sono usati per
trasportare le informazioni il canale quantico è solitamente una
fibra ottica. Il canale pubblico può essere qualsiasi mezzo di
comunicazione, come una linea telefonica.
Ora parliamo per un attimo di informazione. Le
informazioni nel mondo dei computer sono rappresentate da una
serie di 0 e 1 che uniti insieme formano l'informazione. Questi 0
e 1 quando viaggiano in una linea telefonica sono rappresentati
da un voltaggio (solitamente 0V e 5V). Nel caso del canale
quantico le portanti sono i fotoni e come possiamo vedere
possono usare sia la polarizzazione che lo shift di fase.
Figura 4 : Trasmissione tra Alice e Bob.
1. Alice ha 4 polarizzatori, che possono trasmettere
singoli fotoni polarizzati sia verticalmente che
orizzontalmente, a 45° o a -45°. Essa manda una
serie di fotoni attraverso il canale quantico, avendo
scelto a caso uno degli stati di polarizzazione per
ogni fotone.
2. Bob ha 4 analizzatori (dispositivi che possono
analizzare l'angolo di polarizzazione, o più angoli
allo stesso tempo), non due. Un analizzatore
permette a Bob di distinguere tra due fotoni
polarizzati a 45° o a -45°, mentre gli altri gli
permettono di distinguere tra i fotoni polarizzati
verticalmente o orizzontalmente. Si noti che Alice ha
4 polarizzatori e Bob solo due analizzatori. Si noti,
inoltre, come gli 0 e gli 1 sono settati da Alice.
Questo è cruciale. Cosa fa Bob, allora? Egli sceglie
casualmente un analizzatore e lo usa per registrare
ogni protone. In seguito scriverà quale analizzatore
ha usato e cosa ha registrato. Per esempio, Alice
manda un protone polarizzato verticalmente e Bob
sceglie di analizzare solo quelli a +/-45°.
Essenzialmente se Bob sceglie un analizzatore a +/45° ci sono il 50% di probabilità che esso registri
qualcosa, mentre se Bob sceglie l'analizzatore
sbagliato, non ha possibilità di trovare che stato di
117
Appendice C
polarizzazione Alice ha inviato. Dopo aver
scambiato abbastanza fotoni, Bob annuncia nel
canale pubblico la sequenza di analizzatori usata, ma
non il risultato ottenuto.
3. Alice compara la sequenza con la lista dei bits
originariamente inviati, e dice a Bob attraverso il
canale pubblico in che occasione il suo analizzatore
è compatibile con la polarizzazione del fotone. Essa
non deve dire che stato di polarizzazione ha usato.
Se Bob ha usato un analizzatore non compatibile con
il fotone di Alice, il bit è rifiutato. Per i bit
rimanenti, Alice e Bob sanno che hanno lo stesso
valore. I bits che rimangono ad Alice e a Bob
possono essere usati per generare una chiave che essi
potranno utilizzare per crittare il messaggio.
Adesso analizziamo il caso in cui ci sia Eva. Supponiamo
che Eva abbia intercettato entrambi i quanti e l’informazione
inviata attraverso il canale pubblico. Cosa c'è di sbagliato in
quello appena descritto? Ovviamente i bits scoperti non possono
essere usati ancora per la crittazione. Se Eva intercetta la loro
chiave, la correlazione tra i valori dei bits diminuisce. Per
esempio se Eva ha la stessa attrezzatura di Bob e taglia la fibra
e misura il segnale, essa avrà dei bit casuali ogni volta che
sceglierà l'analizzatore sbagliato. Ma avendo intercettato il
segnale, Eva deve mandare un fotone a Bob per coprire le
proprie tracce. Di conseguenza, nel 50% dei casi gli analizzatori
di Alice e Bob coincidono, ma cosa succede nel caso in cui Eva
abbia sbagliato analizzatore? Comunque nella metà dei casi i
fotoni passeranno accidentalmente attraverso l'analizzatore
giusto dalla parte di Bob. Si può vedere ora che la correlazione
tra Alice e Bob scende al 25% in presenza di Eva. In questo caso
Alice e Bob conosceranno l'informazione che è stata
intercettata, quando compareranno le chiavi sul canale pubblico,
notando un grande disaccordo.
Cosa si può ottenere dalla crittografia in pratica? I fotoni
sono dei buoni candidati per trasportare informazioni; essi sono
semplici da produrre a da misurare. L'esempio fatto per la
polarizzazione può essere valido per lo shift di fase. Infatti, è
più usato della polarizzazione. Cosa migliore, i protoni, possono
essere trasmessi attraverso la fibra ottica e la loro attenuazione
è di circa 25 anni (misura di quanti fotoni vengono persi durante
la trasmissione) a una lunghezza d'onda di 1300nm. Questo
significa che i protoni possono viaggiare per 10Km prima che il
50% di essi venga perso. E' importante notare che i protoni non
possono essere amplificati, perchè gli stati dei quanti non
possono essere duplicati.
Certamente questo non è l'unico problema. Ci sono anche
problemi relativi alla linea. La non correlazione tra bit può
anche essere causata da alcune imperefezioni sperimentali. Per
esempio, Alice deve essere sicura di creare fotoni dello stato
scelto.
118
Appendice C
Per superare questi problemi, Alice e Bob devono
applicare un classico algoritmo di gestione degli errori, che
riporti le probabilità di errore negli standard telecomunicativi
(10^-9).
C'è una procedura che Alice e Bob possono usare
conosciuta col nome di "amplificazione privata" in cui gruppi di
bit sono combinati in uno solo. Questa procedura assicura che i
bit combinati coincidano solo se i bit iniziali di Alice e Bob
sono gli stessi.
119
Appendice D
Appendice D
Manuale PGP
Gen. nuove chiavi:
pgp -kg
Aggiunta di chiavi:
pgp -ka file
[portachiavi]
Esrazione di chiavi:
pgp -kx[a] ID file
[portachiavi]
Vedere chiavi:
pgp -kv[v] [ID]
[portachiavi]
Vedere impronte digitali: pgp -kvc [ID]
[portachiavi]
Vedere in dettaglio:
pgp -kc [ID]
[portachiavi]
Rimuovere ID o chiavi: pgp -kr ID
[portachiavi]
(Ripetere per piu' ID su una chiave)
Aggiungere un ID:
pgp -ke ID
[portachiavi]
Modifica frase chiave:
pgp -ke ID
[portachiavi]
Modif. param. affidab.: pgp -kx ID key.tmp [portachiavi]
pgp -kr ID
[portachiavi]
pgp -ka key.tmp
[portachiavi]
Firmare una chiave:
pgp -ks suo_ID [-u mio_ID]
Rimuovere la firma da una
chiave:
pgp -krs ID
[portachiavi]
Revoca, disabilitaz.:
pgp -kd ID
[portachiavi]
Criptare:
pgp -e[a] filetesto dest_ID
Firmare:
pgp -s[a] filetesto
[-u mio_ID]
Firmare e criptare:
pgp -se[a] filetesto dest_ID
[dest2_ID...][-u mio_ID]
Certif. separato:
pgp -sb[a] [+clearsig=on] file
principale [-u mio_ID]
Criptare solo con IDEA: pgp -c filetesto
Decrittare o controllo
firma:
pgp [-d] [-p] filecifrato
(-d per tenere i dati pgp, -p per il nome originale)
Verifica firma separata: pgp filefirma [fileprincipale]
Aggiungere [a] per produrre files ASCII
Aggiungere [-o outfile] per specificare il file di uscita
Aggiungere [+batchmode] per vedere l'uscita errorlevels
Aggiungere [f] per ridirigere i dati ( pgp -f[ARGS] <infile
>outfile )
Aggiungere [w] per distruggere il file in chiaro (dopo la
cifratura)
Aggiunger [m] per permettere la sola visione del testo in chiaro
senza file di uscita
Aggiungere [t] per usare il terminatore di linea Unix
Usare [-@] per specificare destinatari addizionali quando si cifra
120
Appendice E
Appendice E
Prodotti esistenti
1
Netbus
Sono già in commercio alcuni programmi che svolgono
operazioni simili a quelle che ci siamo proposti di raggiungere,
ossia software che intercettano i messaggi provenienti dalla rete.
Netbus è un dei più famosi ed efficienti.
Inizialmente è stato prodotto come gestore di sistemi in
remoto, infatti Netbus e' un potentissimo strumento, che se
usato in maniera giusta, puo' pilotare completamente un'altro
pc, a migliaia di km di distanza, risolvendo molti inconvenienti.
1 Netbus
NETBUS è un programma di BACKDOOR. Grazie a
questo programma l'hacker può teleguidare il vostro computer.
Netbus ha una interfaccia molto più semplice, bisogna solo
conoscere l'indirizzo IP del computer da colpire, poi basta
premere i pulsanti in dotazione col programma client
(programma dell'hacker) come Open CD-ROM che serve ad aprire
e chiudere il cassettino del CD-ROM o Play sound che serve a
fare suonare una musica al server remoto (il vostro computer
colpito da hacker) e moltissimi altri comandi intuitivi.
Figura 1 : Interfaccia di Netbus.
121
Appendice E
Quando un hacker installa il suo "cavallo di troia" nel
vostro computer mette una password per accedere al vostro
computer, in questo modo solo lui potra accedervi; esiste però
una master password. Ciò che lo rende più evoluto degli altri
programmi di Back door è la possibilità di fare la scansione
automatica degli indirizzi IP e la possibilità di avere più persone
sotto il controllo dell'hacker, in questo modo l'hacker non deve
inserire sequenzialmente ogni indirizzo IP ma sarà il programma
stesso a fare la scansione; per fare la scansione basta mettere
xxx.xxx.xxx.0+255 (dove xxx è un numero compreso tra 0 e 255)
in questo modo Netbus farà la scansione da 0 a 255 dell'ultimo
campo dell'indirizzo IP.
Figura 2 : Gestione remota di file con Netbus.
Il programma comprende due file: il programma server e il
programma client.
Il programma server è il file con dimensione minore ed è il
file che infetta il computer del malcapitato, per infettare il
computer il programma deve essere eseguito, il nome del file
generalmente è PATCH.EXE (ma il nome può essere modificato
a proprio piacimento); il programma è difficilmente visibile e si
carica ogni volta che si avvia il computer
Il programma client è quello che usa l'hacker per spiare (o
distruggere) il vostro computer, ha un interfaccia semplicissima
a pulsanti, bisogna solo inserire l'indirizzo IP del computer
infetto (o la gamma di indirizzi) e premere i pulsanti.
Ogni computer infetto ha una sua password di accesso esclusiva
dell'hacker che vi ha infettato.
122
Appendice F
Appendice F
Listati
1
2
3
4
PTerminal
DES
Crittografia
TCP
1 PTerminal
class CMySocket : public CAsyncSocket
{
private:
CDialog* m_pWnd;
// Attributes
public:
// Operations
public:
CMySocket();
virtual ~CMySocket();
SetParent (CDialog *pWnd);
// Overrides
public:
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMySocket)
public:
virtual void OnAccept(int nErrorCode);
virtual void OnConnect(int nErrorCode);
virtual void OnReceive(int nErrorCode);
//}}AFX_VIRTUAL
// Generated message map functions
//{{AFX_MSG(CMySocket)
// NOTE - the ClassWizard will add and remove member
functions here.
//}}AFX_MSG
// Implementation
protected:
};
CMySocket::CMySocket()
{
}
CMySocket::~CMySocket()
{
}
CMySocket::SetParent (CDialog *pWnd)
{
m_pWnd = pWnd;
}
123
Appendice F
// Do not edit the following lines, which are needed by
ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CMySocket, CAsyncSocket)
//{{AFX_MSG_MAP(CMySocket)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
//////////////////////////////////////////////////////////////////
/////CMySocket member functions
void CMySocket::OnAccept(int nErrorCode)
{
if (nErrorCode == 0)
((CPTerminalDlg*)m_pWnd)->OnAccept();
}
void CMySocket::OnConnect(int nErrorCode)
{
if (nErrorCode == 0)
((CPTerminalDlg*)m_pWnd)->OnConnect();
}
void CMySocket::OnReceive(int nErrorCode)
{
if (nErrorCode == 0)
((CPTerminalDlg*)m_pWnd)->OnReceive();
}
class CPTerminalDlg : public CDialog
{
// Construction
private:
CMySocket m_sListenSocket;
CMySocket m_sConnectSocket;
public:
CPTerminalDlg(CWnd* pParent = NULL);
constructor
// standard
void OnAccept();
void OnConnect();
void OnSend();
void OnReceive();
void OnClose();
// Dialog Data
//{{AFX_DATA(CPTerminalDlg)
enum { IDD = IDD_PTERMINAL_DIALOG };
CListBox
m_ctlSent;
CListBox
m_ctlRecvd;
CButton
m_ctlConnect;
CString
m_strMessage;
CString
m_strName;
int
m_iPort;
int
m_iType;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CPTerminalDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX);
support
// DDX/DDV
124
Appendice F
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CPTerminalDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnDestroy();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnRType();
afx_msg void OnBconnect();
afx_msg void OnBsend();
afx_msg void OnBclose();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CPTerminalDlg::CPTerminalDlg(CWnd* pParent /*=NULL*/)
: CDialog(CPTerminalDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CPTerminalDlg)
m_strMessage = _T("");
m_strName = _T("");
m_iPort = 0;
m_iType = -1;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon
in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CPTerminalDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CPTerminalDlg)
DDX_Control(pDX, IDC_LSENT, m_ctlSent);
DDX_Control(pDX, IDC_LRECVD, m_ctlRecvd);
DDX_Control(pDX, IDC_BCONNECT, m_ctlConnect);
DDX_Text(pDX, IDC_EMSG, m_strMessage);
DDX_Text(pDX, IDC_ESERVNAME, m_strName);
DDX_Text(pDX, IDC_ESERVPORT, m_iPort);
DDX_Radio(pDX, IDC_RCLIENT, m_iType);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CPTerminalDlg, CDialog)
//{{AFX_MSG_MAP(CPTerminalDlg)
ON_WM_SYSCOMMAND()
ON_WM_DESTROY()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_RCLIENT, OnRType)
ON_BN_CLICKED(IDC_BCONNECT, OnBconnect)
ON_BN_CLICKED(IDC_BSEND, OnBsend)
ON_BN_CLICKED(IDC_RSERVER, OnRType)
ON_BN_CLICKED(IDC_BCLOSE, OnBclose)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
125
Appendice F
//////////////////////////////////////////////////////////////////
///////////
// CPTerminalDlg message handlers
BOOL CPTerminalDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
SetIcon(m_hIcon,FALSE);
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX,
strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this
automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE);
// Set big icon
SetIcon(m_hIcon, FALSE);
// Set small icon
m_iType = 0;
m_strName = "loopback";
m_iPort = 4000;
UpdateData(FALSE);
m_sConnectSocket.SetParent (this);
m_sListenSocket.SetParent (this);
return TRUE;
control
}
// return TRUE
unless you set the focus to a
void CPTerminalDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
void CPTerminalDlg::OnDestroy()
{
WinHelp(0L, HELP_QUIT);
126
Appendice F
CDialog::OnDestroy();
}
// If you add a minimize button to your dialog, you will need the
code below
// to draw the icon. For MFC applications using the
document/view model,
// this is automatically done for you by the framework.
void CPTerminalDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(),
0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the
user drags
// the minimized window.
HCURSOR CPTerminalDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CPTerminalDlg::OnRType()
{
UpdateData(TRUE);
if (m_iType == 0)
m_ctlConnect.SetWindowText ("C&onnect");
else
m_ctlConnect.SetWindowText ("&Listen");
}
void CPTerminalDlg::OnBconnect()
{
UpdateData(TRUE);
GetDlgItem(IDC_BCONNECT)->EnableWindow(FALSE);
GetDlgItem(IDC_ESERVNAME)->EnableWindow(FALSE);
GetDlgItem(IDC_ESERVPORT)->EnableWindow(FALSE);
GetDlgItem(IDC_STATICNAME)->EnableWindow(FALSE);
127
Appendice F
GetDlgItem(IDC_STATICPORT)->EnableWindow(FALSE);
GetDlgItem(IDC_RCLIENT)->EnableWindow(FALSE);
GetDlgItem(IDC_RSERVER)->EnableWindow(FALSE);
GetDlgItem(IDC_STATICTYPE)->EnableWindow(FALSE);
if (m_iType == 0)
{
//
CAsyncSocket *pSock = new CAsyncSocket;
//
if (m_sConnectSocket.Accept (*pSock))
//
{
//
pSock->Create ();
//
pSock->Connect (m_strName,m_iPort);
//
}
m_sConnectSocket.Create();
m_sConnectSocket.Connect(m_strName,m_iPort);
}
else
{
m_sListenSocket.Create(m_iPort);
m_sListenSocket.Listen();
}
}
void CPTerminalDlg::OnAccept()
{
CAsyncSocket *pSock = new CAsyncSocket;
if (m_sListenSocket.Accept (*pSock))
{
pSock->Create ();
pSock->Connect (m_strName,m_iPort);
}
else
delete pSock;
//m_sListenSocket.Accept(m_sConnectSocket);
GetDlgItem(IDC_EMSG)->EnableWindow(TRUE);
GetDlgItem(IDC_BSEND)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICMSG)->EnableWindow(TRUE);
}
void CPTerminalDlg::OnConnect()
{
GetDlgItem(IDC_EMSG)->EnableWindow(TRUE);
GetDlgItem(IDC_BSEND)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICMSG)->EnableWindow(TRUE);
GetDlgItem(IDC_BCLOSE)->EnableWindow(TRUE);
}
void CPTerminalDlg::OnReceive()
{
char *pBuf = new char[1025];
int iBufSize = 1024;
int iRcvd;
CString strRecvd;
iRcvd = m_sConnectSocket.Receive(pBuf, iBufSize);
if (iRcvd == SOCKET_ERROR)
{
}
else
128
Appendice F
{
pBuf[iRcvd] = NULL;
strRecvd = pBuf;
m_ctlRecvd.AddString(strRecvd);
UpdateData(FALSE);
}
}
void CPTerminalDlg::OnClose()
{
m_sConnectSocket.Close();
GetDlgItem(IDC_EMSG)->EnableWindow(FALSE);
GetDlgItem(IDC_BSEND)->EnableWindow(FALSE);
GetDlgItem(IDC_STATICMSG)->EnableWindow(FALSE);
GetDlgItem(IDC_BCLOSE)->EnableWindow(FALSE);
if (m_iType == 0)
{
GetDlgItem(IDC_BCONNECT)->EnableWindow(TRUE);
GetDlgItem(IDC_ESERVNAME)->EnableWindow(TRUE);
GetDlgItem(IDC_ESERVPORT)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICNAME)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICPORT)->EnableWindow(TRUE);
GetDlgItem(IDC_RCLIENT)->EnableWindow(TRUE);
GetDlgItem(IDC_RSERVER)->EnableWindow(TRUE);
GetDlgItem(IDC_STATICTYPE)->EnableWindow(TRUE);
}
}
void CPTerminalDlg::OnBsend()
{
int iLen;
int iSent;
UpdateData(TRUE);
if (m_strMessage != "")
{
iLen = m_strMessage.GetLength();
iSent = m_sConnectSocket.Send(LPCSTR(m_strMessage),
iLen);
if (iSent == SOCKET_ERROR)
{
}
else
{
m_ctlSent.AddString(m_strMessage);
UpdateData(FALSE);
}
}
}
void CPTerminalDlg::OnBclose()
{
OnClose();
}
129
Appendice F
2 DES
#if
!defined(AFX_DES_H__7AF11A81_11EF_4947_8738_DF9FABD1DD25__INCLUDE)
#define AFX_DES_H__7AF11A81_11EF_4947_8738_DF9FABD1DD25__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class AFX_EXT_CLASS CDes
{
public:
void Decrypt(LPTSTR Key,LPTSTR Data);
CDes();
virtual ~CDes();
void Crypt(LPTSTR Key, LPTSTR Data);
private:
unsigned _int64 artoi(unsigned int *array,unsigned int length);
void itoar(unsigned __int64 int64,unsigned int *array,
unsigned int length);
unsigned _int64 stoi(char *string,unsigned int length);
void itos(char *string,unsigned __int64 int64,
unsigned int length);
void matoar32(unsigned int matrix[][4],unsigned int array[],
unsigned int yStart,unsigned int xStart,
unsigned int yEnd,unsigned int xEnd);
void matoar48(unsigned int matrix[][6],unsigned int array[],
unsigned int yStart,unsigned int xStart,
unsigned int yEnd,unsigned int xEnd);
void matoar56(unsigned int matrix[][7],unsigned int array[],
unsigned int yStart,unsigned int xStart,
unsigned int yEnd,unsigned int xEnd);
void matoar64(unsigned int matrix[][8],unsigned int array[],
unsigned int yStart,unsigned int xStart,
unsigned int yEnd,unsigned int xEnd);
void _strcat(char *strDest,char *strOr);
void arcat(unsigned int *arrayOr1,unsigned int *arrayOr2,
unsigned int *arrayDest,unsigned int lenDest,
unsigned int lenOr);
unsigned _int64 power(unsigned int b,unsigned int e);
void shift(unsigned __int64 &shift,unsigned int nShift);
void Calculate_Keys(unsigned int matrix[][7],
unsigned int iterations);
unsigned __int64 crypt(unsigned __int64 data,
unsigned int iterations);
unsigned __int64 decrypt(unsigned __int64 data,
unsigned int iterations);
void Divide(unsigned int *array,unsigned int matrix[][6],
unsigned int lenAr,unsigned int lenGrp);
unsigned int Index(unsigned matDiv[][6],unsigned matrix[][16],
unsigned row);
void Group(unsigned int *array,unsigned int *arrGrp,
unsigned int lenAr,unsigned int lenGrp);
void Expand(unsigned int *array,unsigned int matrix[][6]);
void Permute_IP(unsigned int *array,unsigned int matrix[][8]);
130
Appendice F
void Permute_P2(unsigned int *array,unsigned int matrix[][4]);
void Permute_FP(unsigned int *array,unsigned int matrix[][8]);
void Reduce56to48(unsigned int *array,
unsigned int matrix[][6]);
void Reduce64to56(unsigned int *array,
unsigned int matrix[][7]);
void Set_Key(unsigned __int64 newKey);
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
EX[8][6];
FP[8][8];
IP[8][8];
__int64 Keys_Array[16];
__int64 L[17];
P1[8][6];
P2[8][4];
__int64 R[17];
Rotation_Array[16];
R1[8][7];
S1[4][16];
S2[4][16];
S3[4][16];
S4[4][16];
S5[4][16];
S6[4][16];
S7[4][16];
S8[4][16];
unsigned _int64 Key;
};
#endif
#include "stdafx.h"
#include "CDes.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////
////
// Construction/Destruction
//////////////////////////////////////////////////////////////////
////
CDes::CDes()
{
//Inizializzazione della prima matrice di riduzione.
R1[0][0] = 57; R1[0][1] = 49; R1[0][2] = 41; R1[0][3]
R1[0][4] = 25; R1[0][5] = 17; R1[0][6] = 9;
R1[1][0] = 1; R1[1][1] = 58; R1[1][2] = 50; R1[1][3]
R1[1][4] = 34; R1[1][5] = 26; R1[1][6] = 18;
R1[2][0] = 10; R1[2][1] = 2; R1[2][2] = 59; R1[2][3]
R1[2][4] = 43; R1[2][5] = 35; R1[2][6] = 27;
R1[3][0] = 19; R1[3][1] = 11; R1[3][2] = 3; R1[3][3]
R1[3][4] = 52; R1[3][5] = 44; R1[3][6] = 36;
R1[4][0] = 63; R1[4][1] = 55; R1[4][2] = 47; R1[4][3]
R1[4][4] = 31; R1[4][5] = 23; R1[4][6] = 15;
= 33;
= 42;
= 51;
= 60;
= 39;
131
Appendice F
R1[5][0]
R1[5][4] =
R1[6][0]
R1[6][4] =
R1[7][0]
R1[7][4] =
= 7; R1[5][1]
38; R1[5][5] =
= 14; R1[6][1]
45; R1[6][5] =
= 21; R1[7][1]
20; R1[7][5] =
= 62; R1[5][2]
30; R1[5][6] =
= 6; R1[6][2]
37; R1[6][6] =
= 13; R1[7][2]
12; R1[7][6] =
= 54; R1[5][3] = 46;
22;
= 61; R1[6][3] = 53;
29;
= 5; R1[7][3] = 28;
4;
//Inizializzazione della prima matrice di permutazione
P1[0][0] = 14; P1[0][1] = 17; P1[0][2] = 11; P1[0][3]
P1[0][4] = 1; P1[0][5] = 5;
P1[1][0] = 3; P1[1][1] = 28; P1[1][2] = 15; P1[1][3]
P1[1][4] = 21; P1[1][5] = 10;
P1[2][0] = 23; P1[2][1] = 19; P1[2][2] = 12; P1[2][3]
P1[2][4] = 26; P1[2][5] = 8;
P1[3][0] = 16; P1[3][1] = 7; P1[3][2] = 27; P1[3][3]
P1[3][4] = 13; P1[3][5] = 2;
P1[4][0] = 41; P1[4][1] = 52; P1[4][2] = 31; P1[4][3]
P1[4][4] = 47; P1[4][5] = 55;
P1[5][0] = 30; P1[5][1] = 40; P1[5][2] = 51; P1[5][3]
P1[5][4] = 33; P1[5][5] = 48;
P1[6][0] = 44; P1[6][1] = 49; P1[6][2] = 39; P1[6][3]
P1[6][4] = 34; P1[6][5] = 53;
P1[7][0] = 46; P1[7][1] = 42; P1[7][2] = 50; P1[7][3]
P1[7][4] = 29; P1[7][5] = 32;
//Inizializzazione della seconda matrice
P2[0][0] = 16; P2[0][1] = 7; P2[0][2]
P2[1][0] = 29; P2[1][1] = 12; P2[1][2]
P2[2][0] = 1; P2[2][1] = 15; P2[2][2]
P2[3][0] = 5; P2[3][1] = 18; P2[3][2]
P2[4][0] = 2; P2[4][1] = 8; P2[4][2]
P2[5][0] = 32; P2[5][1] = 27; P2[5][2]
P2[6][0] = 19; P2[6][1] = 13; P2[6][2]
P2[7][0] = 22; P2[7][1] = 11; P2[7][2]
= 24;
=
6;
=
4;
= 20;
= 37;
= 45;
= 56;
= 36;
di permutazione
= 20; P2[0][3] =
= 28; P2[1][3] =
= 23; P2[2][3] =
= 31; P2[3][3] =
= 24; P2[4][3] =
= 3; P2[5][3] =
= 30; P2[6][3] =
= 4; P2[7][3] =
21;
17;
26;
10;
14;
9;
6;
25;
//Inizializzazione della matrice di permutazione iniziale
IP[0][0] = 58; IP[0][1] = 50; IP[0][2] = 42; IP[0][3] = 34;
IP[0][4] = 26; IP[0][5] = 18; IP[0][6] = 10; IP[0][7] = 2;
IP[1][0] = 60; IP[1][1] = 52; IP[1][2] = 44; IP[1][3] = 36;
IP[1][4] = 28; IP[1][5] = 20; IP[1][6] = 12; IP[1][7] = 4;
IP[2][0] = 62; IP[2][1] = 54; IP[2][2] = 46; IP[2][3] = 38;
IP[2][4] = 30; IP[2][5] = 22; IP[2][6] = 14; IP[2][7] = 6;
IP[3][0] = 64; IP[3][1] = 56; IP[3][2] = 48; IP[3][3] = 40;
IP[3][4] = 32; IP[3][5] = 24; IP[3][6] = 16; IP[3][7] = 8;
IP[4][0] = 57; IP[4][1] = 49; IP[4][2] = 41; IP[4][3] = 33;
IP[4][4] = 25; IP[4][5] = 17; IP[4][6] = 9; IP[4][7] = 1;
IP[5][0] = 59; IP[5][1] = 51; IP[5][2] = 43; IP[5][3] = 35;
IP[5][4] = 27; IP[5][5] = 19; IP[5][6] = 11; IP[5][7] = 3;
IP[6][0] = 61; IP[6][1] = 53; IP[6][2] = 45; IP[6][3] = 37;
IP[6][4] = 29; IP[6][5] = 21; IP[6][6] = 13; IP[6][7] = 5;
IP[7][0] = 63; IP[7][1] = 55; IP[7][2] = 47; IP[7][3] = 39;
IP[7][4] = 31; IP[7][5] = 23; IP[7][6] = 15; IP[7][7] = 7;
//Inizializzazione della matrice di permutazione finale
FP[0][0] = 40; FP[0][1] = 8; FP[0][2] = 48; FP[0][3]
FP[0][4] = 56; FP[0][5] = 24; FP[0][6] = 64; FP[0][7] =
FP[1][0] = 39; FP[1][1] = 7; FP[1][2] = 47; FP[1][3]
FP[1][4] = 55; FP[1][5] = 23; FP[1][6] = 63; FP[1][7] =
FP[2][0] = 38; FP[2][1] = 6; FP[2][2] = 46; FP[2][3]
FP[2][4] = 54; FP[2][5] = 22; FP[2][6] = 62; FP[2][7] =
FP[3][0] = 37; FP[3][1] = 5; FP[3][2] = 45; FP[3][3]
FP[3][4] = 53; FP[3][5] = 21; FP[3][6] = 61; FP[3][7] =
= 16;
32;
= 15;
31;
= 14;
30;
= 13;
29;
132
Appendice F
FP[4][0]
FP[4][4] =
FP[5][0]
FP[5][4] =
FP[6][0]
FP[6][4] =
FP[7][0]
FP[7][4] =
= 36; FP[4][1]
52; FP[4][5] =
= 35; FP[5][1]
51; FP[5][5] =
= 34; FP[6][1]
50; FP[6][5] =
= 33; FP[7][1]
49; FP[7][5] =
= 4; FP[4][2]
20; FP[4][6] =
= 3; FP[5][2]
19; FP[5][6] =
= 2; FP[6][2]
18; FP[6][6] =
= 1; FP[7][2]
17; FP[7][6] =
= 44; FP[4][3]
60; FP[4][7] =
= 43; FP[5][3]
59; FP[5][7] =
= 42; FP[6][3]
58; FP[6][7] =
= 41; FP[7][3]
57; FP[7][7] =
//Inizializzazione della prima matrice di permutazione
EX[0][0] = 32; EX[0][1] = 1; EX[0][2] = 2; EX[0][3]
EX[0][4] = 4; EX[0][5] = 5;
EX[1][0] = 4; EX[1][1] = 5; EX[1][2] = 6; EX[1][3]
EX[1][4] = 8; EX[1][5] = 9;
EX[2][0] = 8; EX[2][1] = 9; EX[2][2] = 10; EX[2][3]
EX[2][4] = 12; EX[2][5] = 13;
EX[3][0] = 12; EX[3][1] = 13; EX[3][2] = 14; EX[3][3]
EX[3][4] = 16; EX[3][5] = 17;
EX[4][0] = 16; EX[4][1] = 17; EX[4][2] = 18; EX[4][3]
EX[4][4] = 20; EX[4][5] = 21;
EX[5][0] = 20; EX[5][1] = 21; EX[5][2] = 22; EX[5][3]
EX[5][4] = 24; EX[5][5] = 25;
EX[6][0] = 24; EX[6][1] = 25; EX[6][2] = 26; EX[6][3]
EX[6][4] = 28; EX[6][5] = 29;
EX[7][0] = 28; EX[7][1] = 29; EX[7][2] = 30; EX[7][3]
EX[7][4] = 32; EX[7][5] = 1;
= 12;
28;
= 11;
27;
= 10;
26;
= 9;
25;
=
3;
=
7;
= 11;
= 15;
= 19;
= 23;
= 27;
= 31;
//Inizializzazione delle 8 tavole (S-Box)
//1°
S1[0][0] = 14; S1[0][1] = 4; S1[0][2] = 13; S1[0][3] = 1;
S1[0][4] = 2; S1[0][5] = 15; S1[0][6] = 11; S1[0][7] = 8;
S1[0][8] = 3; S1[0][9] = 10; S1[0][10] = 6; S1[0][11] = 12;
S1[0][12] = 5; S1[0][13] = 9; S1[0][14] = 0; S1[0][15] = 7;
S1[1][0] = 0; S1[1][1] = 15; S1[1][2] = 7; S1[1][3] = 4;
S1[1][4] = 14; S1[1][5] = 2; S1[1][6] = 13; S1[1][7] = 1;
S1[1][8] = 10; S1[1][9] = 6; S1[1][10] = 12; S1[1][11] = 11;
S1[1][12] = 9; S1[1][13] = 5; S1[1][14] = 3; S1[1][15] = 8;
S1[2][0] = 4; S1[2][1] = 1; S1[2][2] = 14; S1[2][3] = 8;
S1[2][4] = 13; S1[2][5] = 6; S1[2][6] = 2; S1[2][7] = 11;
S1[2][8] = 15; S1[2][9] = 12; S1[2][10] = 9; S1[2][11] = 7;
S1[2][12] = 3; S1[2][13] = 10; S1[2][14] = 5; S1[2][15] = 0;
S1[3][0] = 15; S1[3][1] = 12; S1[3][2] = 8; S1[3][3] = 2;
S1[3][4] = 4; S1[3][5] = 9; S1[3][6] = 1; S1[3][7] = 7;
S1[3][8] = 5; S1[3][9] = 11; S1[3][10] = 3; S1[3][11] = 14;
S1[3][12] = 10; S1[3][13] = 0; S1[3][14] = 6; S1[3][15] = 13;
//2°
S2[0][0] = 15; S2[0][1]
S2[0][4] = 6; S2[0][5] =
S2[0][8] = 9; S2[0][9] =
S2[0][12] = 12; S2[0][13]
S2[1][0] = 3; S2[1][1]
S2[1][4] = 15; S2[1][5] =
S2[1][8] = 12; S2[1][9] =
S2[1][12] = 6; S2[1][13]
S2[2][0] = 0; S2[2][1]
S2[2][4] = 10; S2[2][5] =
S2[2][8] = 5; S2[2][9] =
S2[2][12] = 9; S2[2][13]
S2[3][0] = 13; S2[3][1]
S2[3][4] = 3; S2[3][5] =
S2[3][8] = 11; S2[3][9] =
S2[3][12] = 0; S2[3][13]
= 1; S2[0][2] = 8; S2[0][3] = 14;
11; S2[0][6] = 3; S2[0][7] = 4;
7; S2[0][10] = 2; S2[0][11] = 13;
= 0; S2[0][14] = 5; S2[0][15] = 10;
= 13; S2[1][2] = 4; S2[1][3] = 7;
2; S2[1][6] = 8; S2[1][7] = 14;
0; S2[1][10] = 1; S2[1][11] = 10;
= 9; S2[1][14] = 11; S2[1][15] = 5;
= 14; S2[2][2] = 7; S2[2][3] = 11;
4; S2[2][6] = 13; S2[2][7] = 1;
8; S2[2][10] = 12; S2[2][11] = 6;
= 3; S2[2][14] = 2; S2[2][15] = 15;
= 8; S2[3][2] = 10; S2[3][3] = 1;
15; S2[3][6] = 4; S2[3][7] = 2;
6; S2[3][10] = 7; S2[3][11] = 12;
= 5; S2[3][14] = 14; S2[3][15] = 9;
133
Appendice F
//3°
S3[0][0] = 10; S3[0][1]
S3[0][4] = 6; S3[0][5] =
S3[0][8] = 1; S3[0][9] =
S3[0][12] = 11; S3[0][13]
S3[1][0] = 13; S3[1][1]
S3[1][4] = 3; S3[1][5] =
S3[1][8] = 2; S3[1][9] =
S3[1][12] = 12; S3[1][13]
S3[2][0] = 13; S3[2][1]
S3[2][4] = 8; S3[2][5] =
S3[2][8] = 11; S3[2][9] =
S3[2][12] = 5; S3[2][13]
S3[3][0] = 1; S3[3][1]
S3[3][4] = 6; S3[3][5] =
S3[3][8] = 4; S3[3][9] =
S3[3][12] = 11; S3[3][13]
= 0; S3[0][2] = 9; S3[0][3] = 14;
3; S3[0][6] = 15; S3[0][7] = 5;
13; S3[0][10] = 12; S3[0][11] = 7;
= 4; S3[0][14] = 2; S3[0][15] = 8;
= 7; S3[1][2] = 0; S3[1][3] = 9;
4; S3[1][6] = 6; S3[1][7] = 10;
8; S3[1][10] = 5; S3[1][11] = 14;
= 11; S3[1][14] = 15; S3[1][15] = 1;
= 6; S3[2][2] = 4; S3[2][3] = 9;
15; S3[2][6] = 3; S3[2][7] = 0;
1; S3[2][10] = 2; S3[2][11] = 12;
= 10; S3[2][14] = 14; S3[2][15] = 7;
= 10; S3[3][2] = 13; S3[3][3] = 0;
9; S3[3][6] = 8; S3[3][7] = 7;
15; S3[3][10] = 14; S3[3][11] = 3;
= 5; S3[3][14] = 2; S3[3][15] = 12;
//4°
S4[0][0] = 7; S4[0][1]
S4[0][4] = 0; S4[0][5] =
S4[0][8] = 1; S4[0][9] =
S4[0][12] = 11; S4[0][13]
S4[1][0] = 13; S4[1][1]
S4[1][4] = 6; S4[1][5] =
S4[1][8] = 4; S4[1][9] =
S4[1][12] = 1; S4[1][13]
S4[2][0] = 10; S4[2][1]
S4[2][4] = 12; S4[2][5] =
S4[2][8] = 15; S4[2][9] =
S4[2][12] = 5; S4[2][13]
S4[3][0] = 3; S4[3][1]
S4[3][4] = 10; S4[3][5] =
S4[3][8] = 9; S4[3][9] =
S4[3][12] = 12; S4[3][13]
= 13; S4[0][2] = 14; S4[0][3] = 3;
6; S4[0][6] = 9; S4[0][7] = 10;
2; S4[0][10] = 8; S4[0][11] = 5;
= 12; S4[0][14] = 4; S4[0][15] = 15;
= 8; S4[1][2] = 11; S4[1][3] = 5;
15; S4[1][6] = 0; S4[1][7] = 3;
7; S4[1][10] = 2; S4[1][11] = 12;
= 10; S4[1][14] = 14; S4[1][15] = 9;
= 6; S4[2][2] = 9; S4[2][3] = 0;
11; S4[2][6] = 7; S4[2][7] = 13;
1; S4[2][10] = 3; S4[2][11] = 14;
= 2; S4[2][14] = 8; S4[2][15] = 4;
= 15; S4[3][2] = 0; S4[3][3] = 6;
1; S4[3][6] = 13; S4[3][7] = 8;
4; S4[3][10] = 5; S4[3][11] = 11;
= 7; S4[3][14] = 2; S4[3][15] = 14;
//5°
S5[0][0] = 2; S5[0][1]
S5[0][4] = 7; S5[0][5] =
S5[0][8] = 8; S5[0][9] =
S5[0][12] = 13; S5[0][13]
S5[1][0] = 14; S5[1][1]
S5[1][4] = 4; S5[1][5] =
S5[1][8] = 5; S5[1][9] =
S5[1][12] = 3; S5[1][13]
S5[2][0] = 4; S5[2][1]
S5[2][4] = 10; S5[2][5] =
S5[2][8] = 15; S5[2][9] =
S5[2][12] = 6; S5[2][13]
S5[3][0] = 11; S5[3][1]
S5[3][4] = 1; S5[3][5] =
S5[3][8] = 6; S5[3][9] =
S5[3][12] = 10; S5[3][13]
= 12; S5[0][2] = 4; S5[0][3] = 1;
10; S5[0][6] = 11; S5[0][7] = 6;
5; S5[0][10] = 3; S5[0][11] = 15;
= 0; S5[0][14] = 14; S5[0][15] = 9;
= 11; S5[1][2] = 2; S5[1][3] = 12;
7; S5[1][6] = 13; S5[1][7] = 1;
0; S5[1][10] = 15; S5[1][11] = 10;
= 9; S5[1][14] = 8; S5[1][15] = 6;
= 2; S5[2][2] = 1; S5[2][3] = 11;
13; S5[2][6] = 7; S5[2][7] = 8;
9; S5[2][10] = 12; S5[2][11] = 5;
= 3; S5[2][14] = 0; S5[2][15] = 14;
= 8; S5[3][2] = 12; S5[3][3] = 7;
14; S5[3][6] = 2; S5[3][7] = 13;
15; S5[3][10] = 0; S5[3][11] = 9;
= 4; S5[3][14] = 5; S5[3][15] = 3;
//6°
S6[0][0] = 12; S6[0][1]
S6[0][4] = 9; S6[0][5] =
S6[0][8] = 0; S6[0][9] =
S6[0][12] = 14; S6[0][13]
= 1; S6[0][2] = 10; S6[0][3] = 15;
2; S6[0][6] = 6; S6[0][7] = 8;
13; S6[0][10] = 3; S6[0][11] = 4;
= 7; S6[0][14] = 5; S6[0][15] = 11;
134
Appendice F
S6[1][0] = 10; S6[1][1]
S6[1][4] = 7; S6[1][5] =
S6[1][8] = 6; S6[1][9] =
S6[1][12] = 0; S6[1][13]
S6[2][0] = 9; S6[2][1]
S6[2][4] = 2; S6[2][5] =
S6[2][8] = 7; S6[2][9] =
S6[2][12] = 1; S6[2][13]
S6[3][0] = 4; S6[3][1]
S6[3][4] = 9; S6[3][5] =
S6[3][8] = 11; S6[3][9] =
S6[3][12] = 6; S6[3][13]
= 15; S6[1][2] = 4; S6[1][3] = 2;
12; S6[1][6] = 9; S6[1][7] = 5;
1; S6[1][10] = 13; S6[1][11] = 14;
= 11; S6[1][14] = 3; S6[1][15] = 8;
= 14; S6[2][2] = 15; S6[2][3] = 5;
8; S6[2][6] = 12; S6[2][7] = 3;
0; S6[2][10] = 4; S6[2][11] = 10;
= 13; S6[2][14] = 11; S6[2][15] = 6;
= 3; S6[3][2] = 2; S6[3][3] = 12;
5; S6[3][6] = 15; S6[3][7] = 10;
14; S6[3][10] = 1; S6[3][11] = 7;
= 0; S6[3][14] = 8; S6[3][15] = 13;
//7°
S7[0][0] = 4; S7[0][1]
S7[0][4] = 15; S7[0][5] =
S7[0][8] = 3; S7[0][9] =
S7[0][12] = 5; S7[0][13]
S7[1][0] = 13; S7[1][1]
S7[1][4] = 4; S7[1][5] =
S7[1][8] = 14; S7[1][9] =
S7[1][12] = 2; S7[1][13]
S7[2][0] = 1; S7[2][1]
S7[2][4] = 12; S7[2][5] =
S7[2][8] = 10; S7[2][9] =
S7[2][12] = 0; S7[2][13]
S7[3][0] = 6; S7[3][1]
S7[3][4] = 1; S7[3][5] =
S7[3][8] = 9; S7[3][9] =
S7[3][12] = 14; S7[3][13]
= 11; S7[0][2] = 2; S7[0][3] = 14;
0; S7[0][6] = 8; S7[0][7] = 13;
12; S7[0][10] = 9; S7[0][11] = 7;
= 10; S7[0][14] = 6; S7[0][15] = 1;
= 0; S7[1][2] = 11; S7[1][3] = 7;
9; S7[1][6] = 1; S7[1][7] = 10;
3; S7[1][10] = 5; S7[1][11] = 12;
= 15; S7[1][14] = 8; S7[1][15] = 6;
= 4; S7[2][2] = 11; S7[2][3] = 13;
3; S7[2][6] = 7; S7[2][7] = 14;
15; S7[2][10] = 6; S7[2][11] = 8;
= 5; S7[2][14] = 9; S7[2][15] = 2;
= 11; S7[3][2] = 13; S7[3][3] = 8;
4; S7[3][6] = 10; S7[3][7] = 7;
5; S7[3][10] = 0; S7[3][11] = 15;
= 2; S7[3][14] = 3; S7[3][15] = 12;
//8°
S8[0][0] = 13; S8[0][1]
S8[0][4] = 6; S8[0][5] =
S8[0][8] = 10; S8[0][9] =
S8[0][12] = 5; S8[0][13]
S8[1][0] = 1; S8[1][1]
S8[1][4] = 10; S8[1][5] =
S8[1][8] = 12; S8[1][9] =
S8[1][12] = 0; S8[1][13]
S8[2][0] = 7; S8[2][1]
S8[2][4] = 9; S8[2][5] =
S8[2][8] = 0; S8[2][9] =
S8[2][12] = 15; S8[2][13]
S8[3][0] = 2; S8[3][1]
S8[3][4] = 4; S8[3][5] =
S8[3][8] = 15; S8[3][9] =
S8[3][12] = 3; S8[3][13]
= 2; S8[0][2] = 8; S8[0][3] = 4;
15; S8[0][6] = 11; S8[0][7] = 1;
9; S8[0][10] = 3; S8[0][11] = 14;
= 0; S8[0][14] = 12; S8[0][15] = 7;
= 15; S8[1][2] = 13; S8[1][3] = 8;
3; S8[1][6] = 7; S8[1][7] = 4;
5; S8[1][10] = 6; S8[1][11] = 11;
= 14; S8[1][14] = 9; S8[1][15] = 2;
= 11; S8[2][2] = 4; S8[2][3] = 1;
12; S8[2][6] = 14; S8[2][7] = 2;
6; S8[2][10] = 10; S8[2][11] = 13;
= 3; S8[2][14] = 5; S8[2][15] = 8;
= 1; S8[3][2] = 14; S8[3][3] = 7;
10; S8[3][6] = 8; S8[3][7] = 13;
12; S8[3][10] = 9; S8[3][11] = 0;
= 5; S8[3][14] = 6; S8[3][15] = 11;
//Inizializzazione dell'array delle rotazioni
Rotation_Array[0] = 1;
Rotation_Array[1] = 1;
Rotation_Array[2] = 2;
Rotation_Array[3] = 2;
Rotation_Array[4] = 2;
Rotation_Array[5] = 2;
Rotation_Array[6] = 2;
Rotation_Array[7] = 2;
Rotation_Array[8] = 1;
Rotation_Array[9] = 2;
Rotation_Array[10] = 2;
Rotation_Array[11] = 2;
Rotation_Array[12] = 2;
135
Appendice F
Rotation_Array[13] = 2;
Rotation_Array[14] = 2;
Rotation_Array[15] = 1;
}
CDes::~CDes()
{
}
void CDes::Crypt(LPTSTR Key, LPTSTR Data)
{
unsigned C[8][7];
unsigned Index_Array[64];
unsigned __int64 iCrypted = 0;
unsigned __int64 iData = 0;
unsigned __int64 iKey = 0;
int k = 0;
int iLen = 0;
int iIter = 0;
int iIter_Mod = 0;
iLen = strlen(Data);
if (iLen < 8) iIter++;
else
{
iIter = iLen / 8;
iIter_Mod = iLen % 8;
if (iIter_Mod != 0) iIter++;
}
char *strData = new char[8];
char *strCrypt = new char[64];
char *strRes = new char[iIter * 8];
unsigned __int64 *arrayCrypt = new unsigned __int64[iIter];
strcpy(strRes," ");
strcpy(strCrypt," ");
iKey = _atoi64(Key);
Set_Key(iKey);
itoar(iKey,Index_Array,64);
Reduce64to56(Index_Array,C);
Calculate_Keys(C,16);
for (register int i=0;i<iIter;i++)
{
strcpy(strData," ");
for (register int j=0;j<8;j++)
{
if (k > iLen) strData[j] = NULL;
else
{
strData[j] = Data[k];
k++;
}
}
iData = stoi(strData,iLen);
136
Appendice F
arrayCrypt[i] = crypt(iData,16);
}
for (i=0;i<iIter;i++)
{
itos(strCrypt,arrayCrypt[i],8);
_strcat(strRes,strCrypt);
}
strcpy(Data,strRes);
delete
delete
delete
delete
[]
[]
[]
[]
strData;
strCrypt;
strRes;
arrayCrypt;
}
void CDes::Decrypt(LPTSTR Key, LPTSTR Data)
{
unsigned C[8][7];
unsigned Index_Array[64];
unsigned __int64 iCrypted = 0;
unsigned __int64 iData = 0;
unsigned __int64 iKey = 0;
int k = 0;
int iLen = 0;
int iIter = 0;
int iIter_Mod = 0;
iLen = strlen(Data);
if (iLen < 8) iIter++;
else
{
iIter = iLen / 8;
iIter_Mod = iLen % 8;
if (iIter_Mod != 0) iIter++;
}
char *strData = new char[8];
char *strCrypt = new char[64];
char *strRes = new char[iIter * 8];
unsigned __int64 *arrayCrypt = new unsigned __int64[iIter];
strcpy(strRes," ");
strcpy(strCrypt," ");
iKey = _atoi64(Key);
Set_Key(iKey);
itoar(iKey,Index_Array,64);
Reduce64to56(Index_Array,C);
Calculate_Keys(C,16);
for (register int i=0;i<iIter;i++)
{
strcpy(strData," ");
for (register int j=0;j<8;j++)
{
if (k > iLen) strData[j] = NULL;
137
Appendice F
else
{
strData[j] = Data[k];
k++;
}
}
iData = stoi(strData,iLen);
arrayCrypt[i] = decrypt(iData,16);
}
for (i=0;i<iIter;i++)
{
itos(strCrypt,arrayCrypt[i],8);
_strcat(strRes,strCrypt);
}
strcpy(Data,strRes);
delete
delete
delete
delete
[]
[]
[]
[]
strData;
strCrypt;
strRes;
arrayCrypt;
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO : void Calculate_Keys(unsigned int matrix[][7],
//
unsigned int iterations)
//INPUT
:
matrix[][7] -> matrice ridotta
//
iterations -> iterazioni
//DESCRIZIONE
// La funzione calcola le chiavi usate per la crittazione. Il
//numero di chiavi da calcolare è definito dalla variabile
//iterations.
//////////////////////////////////////////////////////////////////
void CDes::Calculate_Keys(unsigned int matrix[][7], unsigned int
iterations)
{
unsigned
unsigned
unsigned
unsigned
matrixKey[8][6];
__int64 iMsb = 0;
__int64 iLsb = 0;
__int64 iKey = 0;
unsigned
unsigned
unsigned
unsigned
*arrayMsb
*arrayLsb
*arrayCat
*arrayKey
=
=
=
=
new
new
new
new
unsigned[28];
unsigned[28];
unsigned[56];
unsigned[48];
//Vengono creati due array, il primo con la parte bassa della
//matrice il secondo con la parte alta. La matrice utilizzata è
//quella contenente la chiave ridotta a 56 bit.
matoar56(matrix,arrayLsb,0,0,4,7);
matoar56(matrix,arrayMsb,4,0,8,7);
//Vengono convertiti gli array prima calcolati in due interi.
iMsb = artoi(arrayMsb,28);
//D(0)
iLsb = artoi(arrayLsb,28);
//C(0)
//Ciclo principale che permette il calcolo delle chiavi.
for (register unsigned i=0;i<iterations;i++)
138
Appendice F
{
//Vengono shiftati i valori precedentemente calcolati
//secondo il valore contenuto nel array Rotation_Array.
shift(iMsb,Rotation_Array[i]);
shift(iLsb,Rotation_Array[i]);
//I valori appena calcolati vengono convertiti in array.
itoar(iMsb,arrayMsb,28);
itoar(iLsb,arrayLsb,28);
//Gli array appena calcolati vengono concatenati in uno
//solo.
arcat(arrayLsb,arrayMsb,arrayCat,28,28);
//L'array appena calcolato viene ridotto, e trasformato
//in una matrice.
Reduce56to48(arrayCat,matrixKey);
//La matrice risultante dall'ultima operazione viene
//trasformata in un array.
matoar48(matrixKey,arrayKey,0,0,8,6);
//L'array ottenuto viene trasformato in un intero che
//sarà la chiave.
iKey = artoi(arrayKey,48);
//La chiave viene memorizzata.
Keys_Array[i] = iKey;
}
delete
delete
delete
delete
[]
[]
[]
[]
arrayMsb;
arrayLsb;
arrayCat;
arrayKey;
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO : unsigned __int64 decrypt(unsigned __int64 data,
//
unsigned int iterations)
//INPUT
:
data
-> dati da decifrare
//
iterations -> iterazioni
//OUTPUT :
iRes -> dati cifrati
//DESCRIZIONE
// La funzione decritta il dato passato. La variabile iterations
//indica, implicitamente, il numero di chiavi da usare per la
//cifratura.
//////////////////////////////////////////////////////////////////
unsigned __int64 CDes::decrypt(unsigned __int64 data, unsigned int
iterations)
{
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
matrixData[8][8];
matrixExp[8][6];
matrixPer[8][4];
__int64 iExp = 0;
__int64 iXor = 0;
__int64 iRes = 0;
__int64 iCrypted = 0;
j = 0;
x = 16;
139
Appendice F
unsigned
unsigned
unsigned
unsigned
*arrayData = new unsigned[64];
*arrayLR = new unsigned[32];
*arrayExp = new unsigned[48];
*arraySBox = new unsigned[8];
//I dati passati vengono convertiti in un array.
itoar(data,arrayData,64);
//L'array ottenuto viene permutato. Il risultato sarà una
//matrice.
Permute_IP(arrayData,matrixData);
//La parte bassa della matrice viene convertita in un array.
matoar64(matrixData,arrayLR,0,0,4,8);
//L'array risultante viene convertito in un intero. Sarà il
//primo blocco cifrato.
L[0] = artoi(arrayLR,32);
//Vengono effettuate le stesse operazioni precedenti, con
//la parte alta della matrice.
matoar64(matrixData,arrayLR,4,0,8,8);
R[0] = artoi(arrayLR,32);
//Il ciclo applica al blocco dati tutte le chiavi calcolate in
//precedenza.
for (register unsigned i=0;i<iterations + 1;i++)
{
//Il blocco cifrato R[i] viene converito in un array.
itoar(L[i],arrayLR,32);
//All'array risultante viene applicata la matrice di
//espansione.
Expand(arrayLR,matrixExp);
//La matrice ottenuta viene convertita in una array.
matoar48(matrixExp,arrayExp,0,0,8,6);
//L'array ottenuto viene convertito in un intero.
iExp = artoi(arrayExp,48);
//Viene fatta un XOR con il risultato e la chiave
//corrispondente all'iterazione.
iXor = iExp ^ Keys_Array[x];
//Il risultato viene convertito in un array.
itoar(iXor,arrayExp,48);
//L'array risultante viene diviso in gruppi di 6 bit.
Divide(arrayExp,matrixExp,48,6);
//Per ogni gruppo di 6 bit (8 in totale), viene
//calcolato il rispettivo coefficiente contenuto
//nella S-box corrispondente.
arraySBox[j] = Index(matrixExp,S1,j);
j++;
arraySBox[j] = Index(matrixExp,S2,j);
j++;
arraySBox[j] = Index(matrixExp,S3,j);
j++;
arraySBox[j] = Index(matrixExp,S4,j);
140
Appendice F
j++;
arraySBox[j]
j++;
arraySBox[j]
j++;
arraySBox[j]
j++;
arraySBox[j]
j++;
= Index(matrixExp,S5,j);
= Index(matrixExp,S6,j);
= Index(matrixExp,S7,j);
= Index(matrixExp,S8,j);
//I coefficienti ricavati dalle S-box vengono
//riuniti in un unico array.
Group(arraySBox,arrayLR,32,4);
//L'array ottenuto viene permutato.
Permute_P2(arrayLR,matrixPer);
//La matrice ottenuta viene convertita in un array.
matoar32(matrixPer,arrayLR,0,0,8,4);
//L'array viene convertito in un intero.
iRes = artoi(arrayLR,32);
//Viene fatta una XOR con il blocco dati appena
//cifrato e quello precedente.
L[i] = iRes ^ R[i + 1];
R[i] = L[i + 1];
j = 0;
x--;
}
j = 0;
//L'ultimo blocco cifrato di R e di L viene convertito in
//un array e concatenato.
itoar(R[iterations],arrayLR,32);
for (register int k=0;k<32;k++)
{
arrayData[j] = arrayLR[k];
j++;
}
itoar(L[iterations],arrayLR,32);
for (k=0;k<32;k++)
{
arrayData[j] = arrayLR[k];
j++;
}
//L'array ottenuto viene permutato.
Permute_FP(arrayData,matrixData);
//La matrice ottenuta viene convertita in un array.
matoar64(matrixData,arrayData,0,0,8,8);
//L'array viene convertito in un array. Questo sarà il
//dato cifrato.
iCrypted = artoi(arrayData,64);
141
Appendice F
delete
delete
delete
delete
[]
[]
[]
[]
arrayData;
arrayLR;
arrayExp;
arraySBox;
return iCrypted;
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO : unsigned __int64 crypt(unsigned __int64 data,
//
unsigned int iterations)
//INPUT
:
data
-> dati da cifrare
//
iterations -> iterazioni
//OUTPUT :
iRes -> dati cifrati
//DESCRIZIONE
// La funzione critta il dato passato. La variabile iterations
//indica, implicitamente, il numero di chiavi da usare per la
//cifratura.
//////////////////////////////////////////////////////////////////
unsigned __int64 CDes::crypt(unsigned __int64 data, unsigned int
iterations)
{
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
matrixData[8][8];
matrixExp[8][6];
matrixPer[8][4];
__int64 iExp = 0;
__int64 iXor = 0;
__int64 iRes = 0;
__int64 iCrypted = 0;
j = 0;
unsigned
unsigned
unsigned
unsigned
*arrayData = new unsigned[64];
*arrayLR = new unsigned[32];
*arrayExp = new unsigned[48];
*arraySBox = new unsigned[8];
//I dati passati vengono convertiti in un array.
itoar(data,arrayData,64);
//L'array ottenuto viene permutato. Il risultato sarà una
//matrice.
Permute_IP(arrayData,matrixData);
//La parte bassa della matrice viene convertita in un array.
matoar64(matrixData,arrayLR,0,0,4,8);
//L'array risultante viene convertito in un intero. Sarà il
//primo blocco cifrato.
L[0] = artoi(arrayLR,32);
//Vengono effettuate le stesse operazioni precedenti, con
//la parte alta della matrice.
matoar64(matrixData,arrayLR,4,0,8,8);
R[0] = artoi(arrayLR,32);
//Il ciclo applica al blocco dati tutte le chiavi calcolate in
//precedenza.
for (register unsigned i=0;i<iterations + 1;i++)
{
142
Appendice F
//Il blocco cifrato R[i] viene converito in un array.
itoar(R[i],arrayLR,32);
//All'array risultante viene applicata la matrice di
//espansione.
Expand(arrayLR,matrixExp);
//La matrice ottenuta viene convertita in una array.
matoar48(matrixExp,arrayExp,0,0,8,6);
//L'array ottenuto viene convertito in un intero.
iExp = artoi(arrayExp,48);
//Viene fatta un XOR con il risultato e la chiave
//corrispondente all'iterazione.
iXor = iExp ^ Keys_Array[i];
//Il risultato viene convertito in un array.
itoar(iXor,arrayExp,48);
//L'array risultante viene diviso in gruppi di 6 bit.
Divide(arrayExp,matrixExp,48,6);
//Per ogni gruppo di 6 bit (8 in totale), viene
//calcolato il rispettivo coefficiente contenuto
//nella S-box corrispondente.
arraySBox[j] = Index(matrixExp,S1,j);
j++;
arraySBox[j] = Index(matrixExp,S2,j);
j++;
arraySBox[j] = Index(matrixExp,S3,j);
j++;
arraySBox[j] = Index(matrixExp,S4,j);
j++;
arraySBox[j] = Index(matrixExp,S5,j);
j++;
arraySBox[j] = Index(matrixExp,S6,j);
j++;
arraySBox[j] = Index(matrixExp,S7,j);
j++;
arraySBox[j] = Index(matrixExp,S8,j);
j++;
//I coefficienti ricavati dalle S-box vengono
//riuniti in un unico array.
Group(arraySBox,arrayLR,32,4);
//L'array ottenuto viene permutato.
Permute_P2(arrayLR,matrixPer);
//La matrice ottenuta viene convertita in un array.
matoar32(matrixPer,arrayLR,0,0,8,4);
//L'array viene convertito in un intero.
iRes = artoi(arrayLR,32);
//Viene fatta una XOR con il blocco dati appena
//cifrato e quello precedente.
R[i + 1] = iRes ^ L[i];
L[i + 1] = R[i];
j = 0;
}
143
Appendice F
j = 0;
//L'ultimo blocco cifrato di R e di L viene convertito in
//un array e concatenato.
itoar(R[iterations],arrayLR,32);
for (register int k=0;k<32;k++)
{
arrayData[j] = arrayLR[k];
j++;
}
itoar(L[iterations],arrayLR,32);
for (k=0;k<32;k++)
{
arrayData[j] = arrayLR[k];
j++;
}
//L'array ottenuto viene permutato.
Permute_FP(arrayData,matrixData);
//La matrice ottenuta viene convertita in un array.
matoar64(matrixData,arrayData,0,0,8,8);
//L'array viene convertito in un array. Questo sarà il
//dato cifrato.
iCrypted = artoi(arrayData,64);
delete
delete
delete
delete
[]
[]
[]
[]
arrayData;
arrayLR;
arrayExp;
arraySBox;
return iCrypted;
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO : unsigned __int64 artoi(unsigned int *array,
//
unsigned int length)
//INPUT
: array -> array da convertire
//
length -> lunghezza dell'array
//OUTPUT
: iRes
-> array convertito
//DESCRIZIONE
// La funzione converte un array binario (composto da 0 o 1) in un
//intero a 64 bit. La funzione non effettua nessun controllo
// sulla lunghezza dell'array, ma è implicito che esso non debba
//superare i 64 byte. Di conseguenza ogni controllo deve essere
// effettuato prima della chiamata alla funzione.
//////////////////////////////////////////////////////////////////
unsigned _int64 CDes::artoi(unsigned int *array, unsigned int
length)
{
unsigned __int64 iBit = 0;
unsigned __int64 iRes = 0;
unsigned j = 0;
for (register int i=length - 1;i>=0;i--)
{
144
Appendice F
iBit = array[i];
iBit = iBit << j;
iRes |= iBit;
j++;
}
return iRes;
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO : void itoar(unsigned __int64 int64, unsigned int
//
*array, unsigned int length)
//INPUT
: int64 -> intero da convetire
//
array -> array in cui inserire l'intero convertito
//
length -> lunghezza dell'array
//DESCRIZIONE
// La funzione converte un intero fino a 64 bit in un array
//binario (composto da 0 e 1). La funzione non effettua nessun
// controllo sulla lunghezza dell'array, ma è implicito che esso
//debba essere lungo tanto quanto la variabile da convertire e
// non più del tipo più grande (unsigned __int64). Di conseguenza
//ogni controllo deve essere effettuato prima della chiamata alla
// funzione.
//////////////////////////////////////////////////////////////////
void CDes::itoar(unsigned __int64 int64, unsigned int *array,
unsigned int length)
{
unsigned __int64 iCopy = 0;
unsigned __int64 j = 1;
unsigned k = 0;
for (register int i=length - 1;i>=0;i--)
{
j = power(2,i);
iCopy = int64 & j;
switch (iCopy)
{
case 0 : array[k] = 0; k++; break;
default : array[k] = 1; k++;
}
}
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO : void stoi(char *string, unsigned int length)
//INPUT
: string -> stringa da convertire
//
length -> lunghezza della stringa
//OUTPUT :
iRes
-> stringa convertita
//DESCRIZIONE
// La funzione converte una stringa in un intero a 64 bit. La
//funzione non effettua nessun controllo sulla lunghezza della
//stringa,ma è implicito che essa non debba superare i 64 byte. Di
//conseguenza ogni controllo deve essere effettuato prima della
// chiamata alla funzione.
//////////////////////////////////////////////////////////////////
unsigned _int64 CDes::stoi(char *string, unsigned int length)
{
unsigned __int64 iRes = 0;
unsigned __int64 x = 0;
145
Appendice F
for (register unsigned i=0;i<length;i++)
{
x = string[i];
x = x << 8 * i;
iRes |= x;
}
return iRes;
}
void CDes::itos(char *string, unsigned __int64 int64, unsigned int
length)
{
unsigned __int64 x = 0;
register unsigned j = 0;
for (register unsigned i=0;i<length;i++)
{
x = int64;
x = x >> 8 * i;
string[j] = (char )x;
j++;
}
string[length] = NULL;
}
/////Le seguenti funzioni convertono una matrice in un array//////
//////////////////////////////////////////////////////////////////
//PROTOTIPO : void matoarXX(unsigned int matrix[][4], unsigned
//
int *array, unsigned int yStart, unsigned int xStart,
//
unsigned int yEnd, unsigned int xEnd)
//INPUT
: matrix[][x] -> matrice da convertire
//
array
-> array risultato
//
yStart
-> linea di partenza
//
xStart
-> colonna di partenza
//
yEnd
-> linea di arrivo
//
xEnd
-> colonna di arrivo
//DESCRIZIONE
// Le funzioni convertono una matrice di n righe e m colonne, in
//un array pari alla loro dimensione. I parametri indicano
// implicitamente il numero di elementi da estrarre dalla matrice.
//La funzione non effettua nessun controllo sulla lunghezza
// dell' array che deve essere di lunghezza minima pari alla
//grandezza della matrice. Di conseguenza ogni controllo deve
//essere effettuato prima della chiamata alla funzione.
//////////////////////////////////////////////////////////////////
void CDes::matoar32(unsigned int matrix[][4], unsigned int *array,
unsigned int yStart, unsigned int xStart,
unsigned int yEnd, unsigned int xEnd)
{
register unsigned j = 0;
for (register unsigned y=yStart;y<yEnd;y++)
for (register unsigned x=xStart;x<xEnd;x++)
{
array[j] = matrix[y][x];
j++;
}
146
Appendice F
}
void CDes::matoar48(unsigned int matrix[][6], unsigned int *array,
unsigned int yStart, unsigned int xStart,
unsigned int yEnd, unsigned int xEnd)
{
register unsigned j = 0;
for (register unsigned y=yStart;y<yEnd;y++)
for (register unsigned x=xStart;x<xEnd;x++)
{
array[j] = matrix[y][x];
j++;
}
}
void CDes::matoar56(unsigned int matrix[][7], unsigned int *array,
unsigned int yStart, unsigned int xStart,
unsigned int yEnd, unsigned int xEnd)
{
register unsigned j = 0;
for (register unsigned y=yStart;y<yEnd;y++)
for (register unsigned x=xStart;x<xEnd;x++)
{
array[j] = matrix[y][x];
j++;
}
}
void CDes::matoar64(unsigned int matrix[][8], unsigned int *array,
unsigned int yStart, unsigned int xStart,
unsigned int yEnd, unsigned int xEnd)
{
register unsigned j = 0;
for (register unsigned y=yStart;y<yEnd;y++)
for (register unsigned x=xStart;x<xEnd;x++)
{
array[j] = matrix[y][x];
j++;
}
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO :unsigned __int64 power(unsigned int b,unsigned int e)
//INPUT
:
b -> base
//
e -> esponente
//OUTPUT
:
x -> risultato
//DESCRIZIONE
// La funzione calcola l'elevamento a potenza. Sia la base che
//l'esponente devono essere non negativi.
//////////////////////////////////////////////////////////////////
unsigned _int64 CDes::power(unsigned int b, unsigned int e)
{
unsigned __int64 x = 1;
147
Appendice F
if (e == 0) return x;
for (register unsigned __int64 i=1;i<=e;i++) x = x * b;
return x;
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO : void shift(unsigned __int64 &shift, unsigned int
//
n_Shift)
//INPUT
:
shift
-> valore da shiftare
//
n_Shift -> numero di shift (1 o 2)
//OUTPUT
:
shift -> valore shiftato
//DESCRIZIONE
// La funzione simula uno shift circolare supponendo che l'intero
//passato come parametro sia di soli 6 bit.
//////////////////////////////////////////////////////////////////
void CDes::shift(unsigned __int64 &shift, unsigned int nShift)
{
unsigned __int64 iCopy;
iCopy = shift;
switch (nShift)
{
case 1 : if ((shift & 0x8000000) != 0)
{
iCopy &= 0x3ffffff;
iCopy = iCopy << 1;
iCopy++;
}
else iCopy = iCopy << 1;
break;
case 2 : if ((shift & 0x8000000) != 0)
{
iCopy &= 0x7ffffff;
iCopy = iCopy << 1;
iCopy++;
}
else iCopy = iCopy << 1;
if ((iCopy & 0x8000000) != 0)
{
iCopy &= 0x7ffffff;
iCopy = iCopy << 1;
iCopy ++;
}
else iCopy = iCopy << 1;
}
shift = iCopy;
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO : void arcat(unsigned int *arrayOr1, unsigned int
//
*arrayOr2, unsigned int *arrayDest,
//
unsigned int lenOr1,
//
unsigned int lenOr2)
//INPUT
:
arrayOr1 -> primo array da concatenare
//
arrayOr2 -> secondo array da concatenare
//
arrayDest -> array risultato
148
Appendice F
//
lenOr1
-> lunghezza del primo array
//
lenOr2
-> lunghezza del secondo array
//DESCRIZIONE
// La funzione concatena due array della lunghezza specificata dai
//parametri lenOr1 e lenOr2. La funzione non effettua il controllo
//sulla lunghezza degli array, di conseguenza tutti i controlli
//devono essere fatti prima della chiamata alla funzione.
//////////////////////////////////////////////////////////////////
void CDes::arcat(unsigned int *arrayOr1, unsigned int *arrayOr2,
unsigned int *arrayDest, unsigned int lenOr1, unsigned lenOr2)
{
register unsigned j = 0;
for (register unsigned i=0;i<lenOr1;i++)
{
arrayDest[j] = arrayOr1[i];
j++;
}
for (i=0;i<lenOr2;i++)
{
arrayDest[j] = arrayOr2[i];
j++;
}
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO : void _strcat(char *strDest, char *strOr)
//INPUT
: strDest -> stringa destinazione
//
strOr -> stringa d'origine
//DESCRIZIONE
// La funzione concatena due stringhe. La stringa risultante sarà
//contenuta in strDest,inoltre essa sarà del tipo null-terminated.
//////////////////////////////////////////////////////////////////
void CDes::_strcat(char *strDest, char *strOr)
{
int lenDest, lenOr;
lenDest = strlen(strDest);
lenOr = strlen(strOr);
for (register int i=0;i<lenOr;i++)
{
strDest[lenDest - 1] = strOr[i];
lenDest ++;
}
strDest[i + 1] = NULL;
}
//Le seguenti funzioni applicano una matrice predefinita ad un
array//
//////////////////////////////////////////////////////////////////
//PROTOTIPO : void NOME_FUNZIONE(unsigned int *array, unsigned
//
int matrix[][x])
//INPUT
:
array -> array a cui applicare la matrice
//
matrix[][x] -> matrice risultante
//DESCRIZIONE
// Le funzioni applicano la matrice specificata, costruendone una
149
Appendice F
//risultante dall'operazione. Le funzioni seguono lo stesso
// principio di funzionamento, cambia solo la matrice applicata
//(si differenziano, oltre che per i valori, per la grandezza).
// Di seguito sono riassunte le funzioni con le matrici applicate.
// Reduce56to48 -> P1 = prima matrice di permutazione
// Reduce64to56 -> R1 = matrice di riduzione
// Permute_IP
-> IP = matrice di permutazione iniziale
// Permute_P2
-> P2 = seconda matrice di permutazione
// Permute_FP
-> FP = matrice di permutazione finale
// Expand
-> EX = matrice di espansione
//////////////////////////////////////////////////////////////////
void CDes::Reduce56to48(unsigned int *array, unsigned int
matrix[][6])
{
for (register int y=0;y<8;y++)
for (register int x=0;x<6;x++)
matrix[y][x] = array[P1[y][x] - 1];
}
void CDes::Reduce64to56(unsigned int *array, unsigned int
matrix[][7])
{
for (register int y=0;y<8;y++)
for (register int x=0;x<7;x++)
matrix[y][x] = array[R1[y][x] - 1];
}
void CDes::Permute_IP(unsigned int *array, unsigned int
matrix[][8])
{
for (register int y=0;y<8;y++)
for (register int x=0;x<8;x++)
matrix[y][x] = array[IP[y][x] - 1];
}
void CDes::Permute_P2(unsigned int *array, unsigned int
matrix[][4])
{
for (register int y=0;y<8;y++)
for (register int x=0;x<4;x++)
matrix[y][x] = array[P2[y][x] - 1];
}
void CDes::Permute_FP(unsigned int *array, unsigned int
matrix[][8])
{
for (register int y=0;y<8;y++)
for (register int x=0;x<8;x++)
matrix[y][x] = array[FP[y][x] - 1];
}
void CDes::Expand(unsigned int *array, unsigned int matrix[][6])
{
150
Appendice F
for (register int y=0;y<8;y++)
for (register int x=0;x<6;x++)
matrix[y][x] = array[EX[y][x] - 1];
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO : void Divide(unsigned int *array, unsigned int
//
matrix[][6], unsigned int lenAr,
//
unsigned int lenGrp)
//INPUT
:
array -> array da dividere
//
matrix -> matrice risultato
//
lenAr -> lunghezza array
//
lenGrp -> lunghezza gruppo
//DESCRIZIONE
// La funzione divide un array in gruppi della lunghezza
//specificata dalla variabile lenGrp. La massima grandezza
//dell'array è di 48 byte, di conseguenza la grandezza massima
della matrice sarà 8*6. La funzione non effettua nessun controllo
sulla
// lunghezza dell'array e sulla grandezza della matrice. Di
//conseguenza ogni controllo deve essere fatto prima della
//chiamata alla funzione.
//////////////////////////////////////////////////////////////////
void CDes::Divide(unsigned int *array, unsigned int matrix[][6],
unsigned int lenAr, unsigned int lenGrp)
{
register unsigned j = 0;
unsigned y = 0;
while (j < lenAr)
{
for (register unsigned x=0;x<lenGrp;x++)
{
matrix[y][x] = array[j];
j++;
}
y++;
}
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO : void Group(unsigned int *array, unsigned int
//
*arrayGrp, unsigned int lenAr, unsigned
//
int lenGrp)
//INPUT
:
array -> array da raggruppare
//
arrayGrp -> array risultato
//
lenAr -> lunghezza array
//
lenGrp
-> lunghezza dei gruppi
//DESCRIZIONE
// La funzione unisce un array di interi (NON binario) in un unico
//array. La lunghezza dell'array e quella dei gruppi di bit
// viene passata come parametro.
//////////////////////////////////////////////////////////////////
void CDes::Group(unsigned int *array, unsigned int *arrayGrp,
unsigned int lenAr, unsigned int lenGrp)
{
151
Appendice F
unsigned
unsigned
register
register
iCopy = 0;
j = 1;
unsigned k = 0;
unsigned y = 0;
while (k < lenAr)
{
for (register int i=lenGrp - 1;i>=0;i--)
{
j = power(2,i);
iCopy = array[y] & j;
switch (iCopy)
{
case 0 : arrayGrp[k] = 0; k++; break;
default : arrayGrp[k] = 1; k++;
}
}
y++;
}
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO : unsigned Index(unsigned int matDiv[][6], unsigned
//
int matrix[][6], unsigned row)
//INPUT
:
matDiv[][6] -> matrice da indicizzare
//
matrix
-> matrice da cui estrarre i dati
//
row
-> riga della matrice da indicizzare
//OUTPUT :
iRes -> risultato
//DESCRIZIONE
// La funzione preleva dalla matrice matDiv il valore binario e lo
//converte in modo da comporre le coordinate di ricerca
// (m = colonna, n = riga). L'intero risultato della ricerca verrà
//restituito.
//////////////////////////////////////////////////////////////////
unsigned CDes::Index(unsigned int matDiv[][6], unsigned int
matrix[][16],unsigned row)
{
unsigned m = 0;
unsigned n = 0;
unsigned iRes = 0;
if (matDiv[row][0] != 0) m += 2;
if (matDiv[row][5] != 0) m ++;
if
if
if
if
(matDiv[row][1]
(matDiv[row][2]
(matDiv[row][3]
(matDiv[row][4]
!=
!=
!=
!=
0)
0)
0)
0)
n
n
n
n
+= 8;
+= 4;
+= 2;
++;
iRes = matrix[m][n];
return iRes;
}
//////////////////////////////////////////////////////////////////
//PROTOTIPO : void Set_Key(unsigned __int64 newKey)
//INPUT
:
newKey -> nuova chiave
//DESCRIZIONE
// Funzione di interfaccia che setta la chiave.
152
Appendice F
//////////////////////////////////////////////////////////////////
void CDes::Set_Key(unsigned __int64 newKey)
{
Key = newKey;
}
3 Crittografia
Private Function Scan(strC As String) As String
For i = 0 To 26
If (PLOT(i, 0) = strC) Then
PLOT(i, 1) = PLOT(i, 1) + 1
GoTo End_Function
End If
Next i
Scan = False
Exit Function
End_Function:
Scan = True
End Function
Private Function OpenFile(strFileToOpen As String) As String
Dim strFileOpen As String
Dim objFS, txtFile
Set objFS = CreateObject("Scripting.FileSystemObject")
Set txtFile = objFS.OpenTextFile(strFileToOpen)
Do While txtFile.AtEndOfStream <> True
c = txtFile.Read(1)
Scan (LCase(c))
strFileOpen = strFileOpen & c
Loop
txtFile.Close
OpenFile = strFileOpen
End Function
Private Function SaveFile(strFileToSave As String, strFileSave As
String) As Boolean
On Error GoTo Err_Handler
Dim objFS, txtFile
Set objFS = CreateObject("Scripting.FileSystemObject")
Set txtFile = objFS.CreateTextFile(strFileToSave)
txtFile.Write (strFileSave)
txtFile.Close
SaveFile = True
Exit Function
153
Appendice F
Err_Handler:
SaveFile = False
End Function
Private Sub OpenCl()
On Error GoTo Err_Handler
Call InitCDL(cdlSaveOpen, "*.txt", "Apri file in chiaro", _
"File di testo (*.txt)|*.txt|Tutti i file (*.*)|*.*|", _
App.Path, "Open")
cdlSaveOpen.ShowOpen
stbMain.Panels(1).Text = cdlSaveOpen.FileName
Err_Handler:
End Sub
Private Sub SaveCl()
On Error GoTo Err_Handler
Call InitCDL(cdlSaveOpen, "*.txt", "Salva file in chiaro", _
"File di testo (*.txt)|*.txt|", App.Path, "Save")
cdlSaveOpen.ShowSave
Err_Handler:
End Sub
Private Sub OpenCyph()
On Error GoTo Err_Handler
Dim strFilter As String
strFilter = "Cifrario di Cesare (*.csr)|*.csr|Scacchiera di_
Polibio (*.plb)|*.plb|" & _
"Cifrario di Vigénère (*.vgn)|*.vgn|"
Call InitCDL(cdlSaveOpen, "*.csr", "Apri file crittato",
strFilter, App.Path, "Open")
cdlSaveOpen.ShowOpen
Err_Handler:
End Sub
Private Sub SaveCyph()
On Error GoTo Err_Handler
Dim strFilter As String
strFilter = "Cifrario di Cesare (*.csr)|*.csr|Scacchiera di_
Polibio (*.plb)|*.plb|" & _
"Cifrario di Vigénère (*.vgn)|*.vgn|"
Call InitCDL(cdlSaveOpen, "*.csr", "Salva file crittato",
strFilter, App.Path, "Save")
154
Appendice F
cdlSaveOpen.ShowSave
Err_Handler:
End Sub
Private Sub Analize_Click()
On Error GoTo Err_Handler
If ActiveForm Is Nothing Then InitDOC ""
If ActiveForm.txtText.Text = "" Then
Clear
OpenCl
ActiveForm.txtText.Text = OpenFile(cdlSaveOpen.FileName)
ActiveForm.Caption = cdlSaveOpen.FileTitle
InitGRAPH cdlSaveOpen.FileTitle
Else
InitGRAPH cdlSaveOpen.FileTitle
End If
Err_Handler:
End Sub
Private Sub CaesarCrypt_Click()
ActiveForm.txtText.Text = CaesarCyph.Crypt(3, _
ActiveForm.txtText.Text)
End Sub
Private Sub CaesarDecrypt_Click()
ActiveForm.txtText.Text = CaesarCyph.Decrypt(4, _
ActiveForm.txtText.Text)
End Sub
Private Sub MDIForm_Load()
InitVAR
InitDOC ""
End Sub
Private Sub OpenClear_Click()
On Error GoTo Err_Handler
If ActiveForm Is Nothing Then InitDOC ""
Clear
OpenCl
ActiveForm.txtText.Text = OpenFile(cdlSaveOpen.FileName)
ActiveForm.Caption = cdlSaveOpen.FileTitle
Err_Handler:
End Sub
Private Sub OpenCrypt_Click()
155
Appendice F
On Error GoTo Err_Handler
Dim strKey As String
Dim strFile As String
Dim iFil As Integer
Clear
OpenCyph
strFile = OpenFile(cdlSaveOpen.FileName)
If ActiveForm Is Nothing Then InitDOC ""
iFil = cdlSaveOpen.FilterIndex
Select Case iFil
Case 1: ActiveForm.txtText.Text = CaesarCyph.Decrypt(4,_
strFile)
ActiveForm.Caption = cdlSaveOpen.FileTitle
Case 2: ActiveForm.txtText.Text = _
PolibioCyph.Decrypt(strFile)
ActiveForm.Caption = cdlSaveOpen.FileTitle
Case 3: strKey = InputBox("Inserisci la chiave:", _
"Cifrario di Vigénère")
ActiveForm.txtText.Text = _
VigenereCyph.Decrypt(strFile, strKey)
ActiveForm.Caption = cdlSaveOpen.FileTitle
End Select
Err_Handler:
End Sub
Private Sub PolibioCrypt_Click()
ActiveForm.txtText.Text = _
PolibioCyph.Crypt(ActiveForm.txtText.Text)
End Sub
Private Sub PolibioDecrypt_Click()
ActiveForm.txtText.Text = _
PolibioCyph.Decrypt(ActiveForm.txtText.Text)
End Sub
Private Sub Quit_Click()
End
End Sub
Private Sub SaveCrypt_Click()
On Error GoTo Err_Handler
Dim
Dim
Dim
Dim
strKey As String
strCyph As String
bRet As Boolean
iFil As Integer
If (ActiveForm.txtText.Text = "") Then GoTo Err_Handler
SaveCyph
iFil = cdlSaveOpen.FilterIndex
Select Case iFil
156
Appendice F
Case 1: strCyph = CaesarCyph.Crypt(4, _
ActiveForm.txtText.Text)
bRet = SaveFile(cdlSaveOpen.FileName, strCyph)
If (bRet = False) Then GoTo Err_Handler
Case 2: strCyph = _
PolibioCyph.Crypt(ActiveForm.txtText.Text)
bRet = SaveFile(cdlSaveOpen.FileName, strCyph)
If (bRet = False) Then GoTo Err_Handler
Case 3: strKey = InputBox("Inserisci la chiave:", _
"Cifrario di Vigénère")
strCyph = _
VigenereCyph.Crypt(ActiveForm.txtText.Text, strKey)
bRet = SaveFile(cdlSaveOpen.FileName, strCyph)
If (bRet = False) Then GoTo Err_Handler
End Select
Exit Sub
Err_Handler:
MsgBox "Non è stato possibile salvare il file."
End Sub
Private Sub SaveClear_Click()
On Error GoTo Err_Handler
Dim bRet As Boolean
If (ActiveForm.txtText.Text = "") Then GoTo Err_Handler
SaveCl
bRet = SaveFile(cdlSaveOpen.FileName, ActiveForm.txtText.Text)
If (bRet = False) Then GoTo Err_Handler
Exit Sub
Err_Handler:
MsgBox "Non è stato possibile salvare il file."
End Sub
Private Sub tlbMain_ButtonClick(ByVal Button As
MSComctlLib.Button)
Select Case Button.Key
Case "New": If ActiveForm Is Nothing Then InitDOC ""
Case "OpenClear": OpenClear_Click
Case "OpenCyph": OpenCrypt_Click
Case "SaveClear": SaveClear_Click
Case "SaveCyph": SaveCrypt_Click
End Select
End Sub
Private Sub VigenereCrypt_Click()
Dim strKey As String
strKey = InputBox("Inserisci la chiave:", "Cifrario di _
Vigénère")
ActiveForm.txtText.Text = _
VigenereCyph.Crypt(ActiveForm.txtText.Text, strKey)
157
Appendice F
End Sub
Private Sub VigenereDecrypt_Click()
Dim strKey As String
strKey = InputBox("Inserisci la chiave:", "Cifrario di _
Vigénère")
ActiveForm.txtText.Text = _
VigenereCyph.Decrypt(ActiveForm.txtText.Text, strKey)
End Sub
Private Sub Form_Resize()
On Error Resume Next
txtText.Move 100, 100, Me.ScaleWidth - 200, Me.ScaleHeight - 200
End Sub
Private Sub Form_Resize()
On Error Resume Next
mscGraph.Move 100, 100, Me.ScaleWidth - 200, Me.ScaleHeight - 200
End Sub
Public
Public
Public
Public
Public
Public
Public
ALPHA(26) As String
ASCII(255, 1) As String
PLOT(26, 1)
FREQ(26) As String
CaesarCyph As New Caesar
PolibioCyph As New Polibio
VigenereCyph As New Vigenere
Public Sub InitVAR()
j = 0
For i = 97 To 122
ALPHA(j) = Chr(i)
PLOT(j, 0) = ALPHA(j)
j = j + 1
Next i
ALPHA(j) = " "
PLOT(j, 0) = " "
For i = 0 To 255
ASCII(i, 0) = Chr(i)
Next i
FREQ(0)
FREQ(1)
FREQ(2)
FREQ(3)
FREQ(4)
FREQ(5)
FREQ(6)
=
=
=
=
=
=
=
" "
"e"
"a"
"i"
"o"
"n"
"r"
158
Appendice F
FREQ(7) = "t"
FREQ(8) = "l"
FREQ(9) = "s"
FREQ(10) = "c"
FREQ(11) = "d"
FREQ(12) = "u"
FREQ(13) = "p"
FREQ(14) = "m"
FREQ(15) = "v"
FREQ(16) = "g"
FREQ(17) = "h"
FREQ(18) = "b"
FREQ(19) = "f"
FREQ(20) = "q"
FREQ(21) = "z"
FREQ(22) = "j"
FREQ(23) = "k"
FREQ(24) = "w"
FREQ(25) = "x"
FREQ(26) = "y"
End Sub
Public Sub Clear()
For i = 0 To 26
PLOT(i, 1) = 0
Next i
End Sub
Public Sub InitCDL(CDL As CommonDialog,strExt As String,strTitle _
As String, strFilter As String, strInitDir _
As String, strOpenSave As String)
On Error GoTo Err_Handler
CDL.CancelError = True
CDL.DefaultExt = strExt
CDL.DialogTitle = strTitle
CDL.Filter = strFilter
CDL.FilterIndex = 1
CDL.InitDir = strInitDir
Select Case strOpenSave
Case "Save":
CDL.Flags = cdlOFNOverwritePrompt
Case "Open":
CDL.Flags = cdlOFNFileMustExist
End Select
Err_Handler:
End Sub
Public Sub InitDOC(strFilename As String)
Static lDocumentCount As Long
Dim frmD As New frmDoc
lDocumentCount = 1
159
Appendice F
If (strFilename = "") Then strFilename = "Document" &
lDocumentCount
frmD.Caption = strFilename
frmD.Show
End Sub
Public Sub InitGRAPH(strFilename As String)
Static lChartCount
Dim frmG As New frmGraph
If (strFilename = "") Then strFilename = "Chart" & lChartCount
With frmG
.Caption = strFilename
.mscGraph = PLOT
.Show
End With
End Sub
Private Alphabet(255) As String
Public Function Crypt(iSph As Integer, strCrypt As String) As
String
Dim c As Variant
Dim strCrypted As String
Dim iRes As Integer
For i = 1 To Len(strCrypt)
c = Mid(strCrypt, i, 1)
iRes = Find(c)
If ((iRes + iSph) > 255) Then
j = (iRes + iSph) - 255
strCrypted = strCrypted & Alphabet(j)
Else
strCrypted = strCrypted & Alphabet(iRes + iSph)
End If
Next i
Crypt = strCrypted
End Function
Public Function Decrypt(iSph As Integer, strCrypt As String) As
String
Dim c As Variant
Dim strCrypted As String
Dim iRes As Integer
For i = 1 To Len(strCrypt)
c = Mid(strCrypt, i, 1)
iRes = Find(c)
160
Appendice F
If ((iRes - iSph) < 0) Then
j = (iRes - iSph) + 255
strCrypted = strCrypted & Alphabet(j)
Else
strCrypted = strCrypted & Alphabet(iRes - iSph)
End If
Next i
Decrypt = strCrypted
End Function
Private Function Find(vChar As Variant) As Integer
For i = 0 To 255
If (Alphabet(i) = vChar) Then
Find = i
GoTo End_Function
End If
Next i
End_Function:
End Function
Private Sub Init()
Dim c As String
Alphabet(0) = " "
For i = 1 To 255
c = Chr(i)
Alphabet(i) = c
Next i
End Sub
Private Sub Class_Initialize()
Init
End Sub
Private Alphabet(15, 15) As String
Private Sub Find(vChar As Variant, ByRef iY As Integer, ByRef iX
As Integer)
For i = 0 To 15
For j = 0 To 15
If (Alphabet(i, j) = vChar) Then
iY = i
iX = j
GoTo End_Function
End If
Next j
Next i
End_Function:
End Sub
161
Appendice F
Private Function HexToDec(c As Variant) As Long
Dim lRes As Long
If ((c >= Hex(10)) And (c <=
Select Case c
Case Hex(10): lRes =
Case Hex(11): lRes =
Case Hex(12): lRes =
Case Hex(13): lRes =
Case Hex(14): lRes =
Case Hex(15): lRes =
End Select
Else
lRes = c
End If
Hex(15))) Then
10
11
12
13
14
15
HexToDec = lRes
End Function
Public Function Crypt(strCrypt As String) As String
Dim
Dim
Dim
Dim
Dim
Dim
c As Variant
strCrypted As String
l As Long
x As Integer
y As Integer
j As Long
j = 0
For i = 1 To Len(strCrypt)
c = Mid(strCrypt, i, 1)
Find c, y, x
strCrypted = strCrypted & Hex(y) & Hex(x)
Next i
Crypt = strCrypted
End Function
Public Function Decrypt(strCrypt As String) As String
Dim
Dim
Dim
Dim
Dim
c As Variant
strCrypted As String
x As Long
y As Long
p As Long
p = 1
For i = 1 To Len(strCrypt) / 2
c
y
p
c
x
p
=
=
=
=
=
=
Mid(strCrypt, p, 1)
HexToDec(c)
p + 1
Mid(strCrypt, p, 1)
HexToDec(c)
p + 1
162
Appendice F
strCrypted = strCrypted & Alphabet(y, x)
Next i
Decrypt = strCrypted
End Function
Private Sub Init()
Dim c As Integer
c = 0
For i = 0 To 15
For j = 0 To 15
Alphabet(i, j) = Chr(c)
c = c + 1
Next j
Next i
End Sub
Private Sub Class_Initialize()
Init
End Sub
Private Alphabet(255, 255) As String
Private Sub FindRow(vChar As Variant, y As Integer, x As Integer,
ByRef iY As Integer, ByRef iX As Integer)
On Error GoTo End_Function
For i = y To 255
For j = x To 255
If (Alphabet(i, j) = vChar) Then
iY = i
iX = j
GoTo End_Function
End If
Next j
Next i
End_Function:
End Sub
Private Sub FindCol(vChar As Variant, y As Integer, x As Integer,
ByRef iY As Integer, ByRef iX As Integer)
On Error GoTo End_Function
For j = x To 255
For i = y To 255
If (Alphabet(i, j) = vChar) Then
iY = i
iX = j
GoTo End_Function
163
Appendice F
End If
Next i
Next j
End_Function:
End Sub
Public Function Decrypt(strCrypt As String, strKey As String) As
String
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
strCrypted As String
j As Integer
cCrypt As String
cKey As String
cRes As String
iYCrypt As Integer
iXCrypt As Integer
iYKey As Integer
iXKey As Integer
j = 1
For i = 1 To Len(strCrypt)
If (j > Len(strKey)) Then j = 1
cCrypt = Mid(strCrypt, i, 1)
cKey = Mid(strKey, j, 1)
FindCol cKey, 0, 0, iYKey, iXKey
FindRow cCrypt, iYKey, 0, iYCrypt, iXCrypt
cRes = Alphabet(0, iXCrypt)
strCrypted = strCrypted & cRes
j = j + 1
Next i
Decrypt = strCrypted
End Function
Public Function Crypt(strCrypt As String, strKey As String) As
String
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
strCrypted As String
j As Integer
cCrypt As String
cKey As String
cRes As String
iYCrypt As Integer
iXCrypt As Integer
iYKey As Integer
iXKey As Integer
j = 1
For i = 1 To Len(strCrypt)
164
Appendice F
If (j > Len(strKey)) Then j = 1
cCrypt = Mid(strCrypt, i, 1)
cKey = Mid(strKey, j, 1)
FindRow cCrypt, 0, 0, iYCrypt, iXCrypt
FindCol cKey, 0, 0, iYKey, iXKey
cRes = Alphabet(iYKey, iXCrypt)
strCrypted = strCrypted & cRes
j = j + 1
Next i
Crypt = strCrypted
End Function
Private Sub Init()
Dim
Dim
Dim
Dim
Dim
x
y
j
c
k
As
As
As
As
As
Integer
Integer
Integer
Integer
Integer
j = 0
c = 0
k = 0
For y = 0 To 255
For x = 0 To (255 - j)
Alphabet(y, x) = Chr(k)
k = k + 1
Next x
If Not (j = 0) Then
For i = (255 - j) + 1 To 255
Alphabet(y, i) = Chr(c)
c = c + 1
Next i
End If
c = 0
j = j + 1
k = j
Next y
End Sub
Private Sub Class_Initialize()
Init
End Sub
165
Appendice F
4 TCP
/***********GENERATORI DI PACCHETTI TCP*************************/
/* Dichiarazione delle librerie principali usate nel programma */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
<stdlib.h>
<stdio.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<arpa/inet.h>
<netinet/in_systm.h>
<netinet/ip.h>
<netinet/tcp.h>
<string.h>
<unistd.h>
<time.h>
<stdlib.h>
<stdio.h>
<sys/types.h>
/* Dichiarazione dei prototipi delle funzioni */
void tcp_gen(char *packet,unsigned short sport,unsigned short
dport,unsigned long seq,unsigned long ack);
void udp_gen(char *packet,unsigned short sport,unsigned short
dport,unsigned short length);
void ip_gen(char *packet,unsigned char protocol,struct in_addr
saddr,struct in_addr daddr,unsigned short length);
unsigned short trans_check(unsigned char proto, char *packet,int
length, struct in_addr source_address,
struct in_addr dest_address);
unsigned short in_cksum(unsigned short *addr,int len);
#define IPVERSION 4 /* versione del pacchetto IP */
#define DEFAULT_TTL 60 // Definizione del tempo di vita dei
pacchetti //
#define TH_OFFSET 5
#define TCP_WINDOW_SIZE 512 /*larghezza della finestra del tcp */
/* struttura per il calcolo del checksum sul pacchetto tcp*/
struct psuedohdr {
struct in_addr source_address;
struct in_addr dest_address;
unsigned char place_holder;
unsigned char protocol;
unsigned short length;
} psuedohdr;
/****** calcolo del checksum sul tcp header *******************/
unsigned short trans_check(unsigned char proto,char *packet,int
length,struct in_addr source_address,
struct in_addr dest_address)
{
char *psuedo_packet;
166
Appendice F
unsigned short answer;
/* compilazione della struttura pseudohdr tcp */
psuedohdr.protocol = proto;
psuedohdr.length = htons(length);
psuedohdr.place_holder = 0;
psuedohdr.source_address = source_address;
psuedohdr.dest_address = dest_address;
/* allocazione della struttura pseudohdr */
if((psuedo_packet = malloc(sizeof(psuedohdr) + length)) == NULL)
{
perror("malloc");
exit(1);
}
/* copia la struttura pseudohdr nella blocco puntato da
pseudo_packet */
memcpy(psuedo_packet,&psuedohdr,sizeof(psuedohdr));
memcpy(psuedo_packet,&psuedohdr,sizeof(psuedohdr,packet,length));/
/memcpy((psuedo_packet + sizeof(psuedohdr,packet,length)));
/* applica l'algoritmo del checksum allo pseudo pacchetto*/
answer = (unsigned short)in_cksum((unsigned short*)psuedo_packet,
length + sizeof(psuedohdr)));
free( psuedo_packet ) ;
return answer;
}
/************************* algoritmo del checksum **************/
unsigned short in_cksum(unsigned short *addr,int len)
{
register int sum = 0;
u_short answer = 0;
register u_short *w = addr;
register int nleft = len;
/*Questo ciclo somma nel registro accumulatore (sum) 32 bit le
parole di 16 bit che vengono estratte dalla struttura addr.*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
/* se la lunghezza del campo dati è numero dispari viene
completato */
/* con un 0 addizionale .*/
if (nleft == 1) {
*( u_char * )( &answer ) = *( u_char * )w ;
sum += answer;
}
/* viene calcolato il complemento a 1 della somma delle word */
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}
/*********************** generatore pacchetto IP ***************/
167
Appendice F
void ip_gen(char *packet,unsigned char protocol,struct in_addr
saddr,struct in_addr daddr,unsigned short length)
{
/* definisco un puntatore alla struttura */
struct iphdr *iphdr;
/* La variabile pacchetto diventa puntatore alla struttura iphdr
*/
iphdr = (struct iphdr *)packet;
memset((char *)iphdr,'\0',sizeof(struct iphdr));
/* compilo la struttura ip */
iphdr->ihl = 5;
iphdr->version = IPVERSION;
/* BIG ENDIAN e LITTLE ENDIAN */
#ifdef IP_LEN_HORDER
iphdr->tot_len = length;
#else
iphdr->tot_len = htons(length);
#endif /* IP_LEN_HORDER */
iphdr->id = htons(getpid());
iphdr->ttl = DEFAULT_TTL;
iphdr->protocol = protocol;
iphdr->saddr = saddr.s_addr;
iphdr->daddr = daddr.s_addr;
/* calcola il checksum del pacchetto*/
iphdr->check = (unsigned short)in_cksum((unsigned short *)iphdr,
sizeof(struct iphdr));
return;
}
/***dichiarazione del prototipo della funzione tcp_gen ********/
void tcp_gen(char *packet,unsigned short sport,unsigned short
dport, unsigned long seq,unsigned long ack)
{
/* puntatore alla struttura tcphdr */
struct tcphdr *tcp;
/* Cast di packet da (char *) a (struct tcphdr*) */
tcp = (struct tcphdr *)packet;
memset((char *)tcp,'\0',sizeof(struct tcphdr));
/* compilazione della struttura tcp */
tcp->source = htons(sport);
tcp->dest = htons(dport);
tcp->seq = htonl(seq);
tcp->ack_seq = htonl(ack);
tcp->res1 = 0;
tcp->doff = TH_OFFSET;
tcp->window = htons(TCP_WINDOW_SIZE);
tcp->fin = 1;
return;
}
/*************** M A I N **************************************/
168
Appendice F
/*argv:
1-porta sorgente
2-indirizzo sorgente
3-porta destinazione
4-indirizzo destinazione
*/
int main(int argc,char *argv[])
{
/* vettore pacchetto di lunghezza ip header + tcp header */
unsigned char packet[ sizeof(struct iphdr) + sizeof(struct
tcphdr) ];
/* sockaddr_in struttura della socket */
struct sockaddr_in mysocket;
/* porte sorgenti e destinazioni */
unsigned short sport, dport;
/* struttura per l'indirizzamento ID/RETE ID/HOST */
struct in_addr saddr, daddr;
/* puntatore alla struttura tcphdr */
struct tcphdr *tcp;
unsigned long seq, ack;
int sockd, on = 1;
/* Prelevo gli argomenti dalla riga di comando */
if(argc < 5) {
fprintf(stderr,"usare: %s porta_sorg. indirizzo_sorg. porta_dest.
indirizzo_dest\n", argv[0]);
exit(1);
}
/* Compila la struttura per le socket con porta sorgente e
indirizzo sorgente */
sport = (unsigned short)atoi(argv[1]);
saddr.s_addr = inet_addr(argv[2]);
/* Compila la struttura per le socket con porta destinazione e
indirizzo destinazione */
dport = (unsigned short)atoi(argv[3]);
daddr.s_addr = inet_addr(argv[4]);
/* Creo il socket descriptor con l'opzione socket raw */
if((sockd = socket(AF_INET,SOCK_RAW,IPPROTO_RAW)) < 0) {
perror("socket");
exit(1);
}
/* Setto alcune opzioni inerenti al livello del protocollo IP */
if(setsockopt(sockd,IPPROTO_IP,IP_HDRINCL,(char *)&on,sizeof(on))
< 0) {
perror("setsockopt");
exit(1);
}
/* Genero numero di sequenza ed ack casuali */
srand(getpid());
seq = rand()%time( NULL );
ack = rand()%time( NULL );
/* Genero pacchetto IP */
169
Appendice F
ip_gen(packet,IPPROTO_TCP,saddr,daddr,sizeof(packet));
/* Sposto il puntatore della struttura tcp header della
dimensione del */
/* pacchetto + la struttura ip header */
tcp = (struct tcphdr *)(packet + sizeof(struct iphdr));
/* Genero il pacchetto TCP */
tcp_gen((char *)tcp,sport,dport,seq,ack);
/* checksum calcolato sul pacchetto IP */
tcp->check = trans_check(IPPROTO_TCP,(char *)tcp,
sizeof(struct tcphdr),
saddr,
daddr);
/*inizializza la struttura mysocket */
memset(&mysocket,'\0',sizeof(mysocket));
/*Compilo la struttura mysocket */
mysocket.sin_family = AF_INET;
mysocket.sin_port = htons(dport);
mysocket.sin_addr = daddr;
/* Spedisco il pacchetto da me creato con il flag fin a a 1
secondo i parametri immessi da linea di comando.*/
if(sendto(sockd,&packet,sizeof(packet),0x0,(struct sockaddr
*)&mysocket,
sizeof(mysocket)) != sizeof(packet)) {
perror("sendto");
exit(1);
}
exit(0);
}
/****************************************************************/
170
Glossario
GLOSSARIO
Albam
metodo crittografico usato dagli ebrei.
Consiste nel dividere in due parti l’alfabeto e
nel sostituire ogni lettera con la
corrispondente nell’altra metà.
ARPA
da Advanced Research Project Agency,
Agenzia per progetti di ricerca avanzata.
Agenzia del Dipartimento della Difesa
statunitense, attualmente ribattezzata
DARPA, fondata nel 1958 per il
finanziamento della ricerca militare.
ARPANet
da Advance Research Project Agency
Network, rete dell’Agenzia per progetti di
ricerca avanzata. Rete a lunga distanza creata
nel 1969 dell’Agenzia per progetti di ricerca
avanzata (ARPA) statunitense, in
collaborazione con le principali università e
centri di ricerca, con il fine di utilizzare la
comunicazione di dati ad alta velocità per la
collaborazione scientifica e le operazioni
militari.
Atbash
dall’unione delle prime e dalle ultime due
lettere dell’alfabeto ebraico, Aleph Taw Beth
Shin. Codice di cifratura usato nel Vecchio
Testamento dal profeta Geremia, consiste
nel sostituire la prima lettera dell’alfabeto
con l’ultima la seconda con la penultima e
così via.
Brute force
nella crittografia e in altri campi matematici,
tecnica di risoluzione dei problemi che
impiega un computer programmato per
eseguire ripetutamente un compito semplice,
nella speranza di trovare la risposta.
Checksum
somma di controllo. Tecnica di rilevazione
di errori che verifica la corretta ricezione di
un blocco dati. Consiste nell’eseguire la
somma dei valori dei bit contenuti nel
blocco dati trasmesso e nel confrontarla con
la somma analoga eseguita in ricezione.
DARPA
da Defense Advanced Research Project
Agency, Agenzia della Difesa per progetti di
ricerca avanzata. Attuale denominazione
dell’Agenzia per progetti di ricerca avanzata
del Dipartimento della Difesa Statunitense.
171
Glossario
DES
da Data Encryption Standard, standard di
cifratura dati. Metodo di cifratura sviluppato
da IBM e certificata nel 1977 dal governo
USA come tecnica ufficiale di cifratura per
informazioni non classificate; sebbene abbia
perso la certificazione nel 1998, è ancora
ampiamente usato.
DLL
da Dynamic Link Library, libreria di
collegamento dinamico. Modulo software
dell’ambiente Windows contenente codice
eseguibile e dati che possono essere
richiamati e usati da applicazioni Windows e
da altre DLL. Funzioni e dati in una DLL
sono caricati e linkati durante l’esecuzione,
quando sono richiamati da un’applicazione o
altre DLL.
FTP
da File Transfer Protocol, protocollo di
trasferimento file. Protocollo Internet per lo
scambio di file con computer ospiti remoti,
basato sul modello client/server. FTP può
copiare dall’ospite uno o più file e fornisce
gli strumenti necessari per identificare la
directory corrente sull’ospite remoto,
elencare i suoi file, cambiare directory e
rinominare i file o cancellarli.
Hash
funzione che, dato un numero in ingresso, ne
genera un altro dal numero di cifre
prestabilite. Da quest’ultimo non è possibile
ricavare il numero che l’ha generato.
Host
computer usato da più di un utente come
mezzo di accesso a Internet, di cui funge da
punto terminale di trasferimenti dati.
HTTP
da HyperText Transport Protocol, protocollo
per trasferimento di ipertesti. Protocollo e
software servitore che lo implementa per la
navigazione di ipertesti usato da World Wide
Web.
ICMP
da Internet Control Message Protocol,
protocollo di controllo dei messaggi in
Internet. Protocollo standard che gestisce la
situazione in cui un instradatore sia
congestionato o comunque non in grado
d’inviare a destinazione un datagramma.
172
Glossario
LAN
da Local Area Network, rete locale.
Collegamento di computer di vario tipo
entro un’area limitata (10 m – 10 Km) per
mezzo di un canale fisico costituito da cavo
coassiale, doppino telefonico o fibra ottica.
MFC
da Microsoft Foundation Classes, classi
fondate da Mircrosoft. Insieme di librerie
DLL, che forniscono numerose funzioni,
come l’uso dei socket e la gestione delle
finestre.
NETBIOS
da NETwork Basic Input/Output System,
sistema di base di ingresso/uscita di rete.
Gruppo di funzioni di servizio, residenti in
memoria di sola lettura, che favoriscono la
trasmissione e la ricezione di dati fra un
computer e la scheda di collegamento a una
rete locale.
NIST
da National Institute for Standards and
Technology, Istituto nazionale per gli
standard e la tecnologia. Istituto erede del
National Bureau of Standards (NBS) e
riconosciuto dall’ANSI, che definisce le
specifiche per gli appalti pubblici.
NNTP
da Network News Transfer Protocol,
protocollo di trasferimento delle notizie di
rete. Nella rete Usenet, protocollo standard
che regola la diffusione dei messaggi ai siti
che si siano accordati per ricevere le notizie
di rete.
NSF
da National Science Foundation, Fondazione
nazionale per la scienza. Agenzia
indipendente del governo statunitense,
fondata nel 1950 per promuovere la scienza e
la tecnologia attraverso la sponsorizzazione
di ricerche scientifiche, ingegneristiche ed
educative.
NSFNet
rete a commutazione di pacchetto ad alta
velocità basata sui protocolli TCP/IP, che
costituisce una delle dorsali di Internet e
gestisce i dati prodotti da reti regionali.
173
Glossario
OSI
da Open System Interconnection,
interconnessione di sistemi aperti. Standard
internazionale per l’organizzazione di reti
locali, definito dall’Organizzazione
internazionale per gli standard (ISO) e
dall’Istituto di ingegneri elettrici ed
elettronici (IEEE) nei primi anni ’80.
PGP
da Pretty Good Privacy, riservatezza molto
buona. Software di cifratura di pubblico
dominio sviluppato da Phil Zimmerman.
da Post Office Protocol 3, protocollo
postale. Protocollo che specifica gli scambi
di posta elettronica tra un PC e un provider.
POP3
Router
apparato che esegue l’interconnessione di
reti locali multiprotocollo. Opera allo strato
3 del modello OSI e utilizza l’indirizzo
logico contenuto in un pacchetto di dati per
decidere il percorso da utilizzare per
l’instradamento all’utente di destinazione; in
presenza di più percorsi tra due LAN, li può
utilizzare tutti in modo ottimizzato.
SMTP
da Simple Mail Transfer Protocol, protocollo
semplice per il trasporto di posta. Nello
strato di applicazione di Internet, protocollo
che regola il formato dei messaggi di posta
elettronica. Sviluppato inizialmente da
ARPANet, è diventato il protocollo mondiale
di fatto per i messaggi di posta elettronica.
Socket
nell’indirizzamento di Internet,
combinazione di un indirizzo IP, che
identifica un computer ospite, con un
indirizzo di porta, che identifica
un’applicazione in funzione sull’ospite.
Steganografia
deriva dalle parole greche steganòs, coperto e
gràphein, scrivere. Tecnica di comunicazione
segreta basata sull’occultamento del
messaggio.
nell’indirizzamento di Internet, subunità
nella rete di un’organizzazione, che è stata
identificata come entità distinta ai fini
dell’instradamento di datagrammi,
modificando la struttura degli indirizzi IP.
Subnet
174
Glossario
TCP/IP
da Transmission Control Protocol/Internet
Protocol, protocollo di controllo di
trasmissione/protocollo Internet. Sigla che
indica propriamente i due protocolli
principali di Internet, il protocollo di
controllo di trasmissione e il protocollo
Internet, progettati alla fine degli anni ’70
da Bobert E. Kahn e Vinton G. Cerf a
Berkeley.
Telnet
nome di un protocollo e del software che lo
implementa, che definisce un terminale
virtuale di rete e permette a un utente di
entrare in un computer ospite remoto.
UDP
da User Datagram Protocol, protocollo di
datagramma di utente. Nello strato di
trasporto di Internet, protocollo non
affidabile e senza collegamento che non
tenta di verificare se un messaggio sia stato
ricevuto.
Unix
sistema operativo multiutente/multitask
sviluppato a partire dal 1969 da Ken
Thompson nel Bell Telephone Labs. Scritto
originariamente nel linguaggio assembly, è
stato presto tradotto in C, potendo così
essere trasportato su numerosi sistemi.
WAN
da Wide – Area Network, rete ad ampio
raggio. Rete dati pubblica, con topologia di
solito a maglia o ibrida, che impiega linee
telefoniche dedicate o satelliti per collegare
più reti locali (LAN), estendendosi su una
regione geografica più estesa di un’area
metropolitana.
Winsock
nell’ambiente Microsoft Windows, file di una
libreria DLL che contiene le informazioni e
le procedure necessarie a Windows per
interfacciarsi con i protocolli TCP/IP.
175
Bibliografia
BIBLIOGRAFIA
Visual C++ 6 Guida completa
Davis Chapman
Apogeo
Dizionario di informatica
Angelo Gallippi
Tecniche nuove
The Alan Turing home page
www.turing.org.uk/turing
Eli Biham’s home page
www.cs.technion.ac.il/~biham/
MAW 97 CIPHERS The Enigma machine
www.math.arizona.edu/~dsl/enigma.htm
Riksoft – Software – Protezione – Servizi
www.riksoft.com/indexok.asp?Goto=critlogia.htm
Sockaddr.com
www.sockaddr.com/
MSDN Library
www.microsoft.com
Manuali.it
www.manuali.it
WWII Codes and cyphers
www.codesandciphers.org.uk
176