Sei sulla pagina 1di 74

CRITTOGRAFIA

DEFINIZIONI:

1) CRITTOANALISI: E’ chi si occupa di attaccare i sistemi crittografici


2) CRITTOGRAFIA: E’ chi costruisce il sistema crittografico
3) CRITTOLOGIA: Racchiude le due classi precedenti

4) PLAINTEXT: Testo in chiaro, il messaggio segreto che il mittente vuole


spedire sul canale

5) CIPHERTEXT: Testo cifrato, ricavato a partire dal plaintext cifrato con un


opportuno algoritmo

6) LEGGE DI KERCKHOFF: Chi difende un sistema crittografico deve mettersi


nella situazione peggiore, cioè quella in cui l’attaccante conosce tutto del
mittente tranne il plaintext e la chiave

COMUNICAZIONE SICURA:

Si abbia, per esempio, una comunicazione tra due agenti, Alice e Bob.
Il terzo agente, Eve, vuole ascoltare la loro conversazione senza essere scoperta. Alice
manda un messaggio a Bob detto plainext o testo in chiaro criptandolo in una
modalità decisa assieme a priori: tale metodo si assume sia noto anche ad Eve. Con la
chiave il testo in chiaro è criptato e reso segreto. Quando Bob riceve il messaggio lo
decritta con la chiave a partire da quello che possiede, ovvero il crittotesto.

Eve, in questa configurazione, potrebbe:

→ intercettare il messaggio;

→ trovare la chiave e leggere in chiaro tutti i messaggi criptati con quella specifica
chiave;

→ cambiare il messaggio che ha mandato Alice a Bob sostituendolo con un altro in


modo da compromettere Alice nei confronti di Bob;

→ far finta di essere davvero Alice e comunicare con Bob che crederà quindi di parlare
con la vera Alice.
TIPOLOGIE DI ATTACCO:

1) C-ONLY: L’attaccante, Eva, ha a disposizione solo il ciphertext che ha


recuperato dal canale, l’unica cosa che può fare è eseguire un attacco a FORZA
BRUTA, cioè provando a calcolare tutte le possibili chiavi per decifrare il
ciphertext.

2) KNOWN PLAINTEXT: L’attaccante riesce a recuperare il ciphertext e


successivamente anche il relativo plaintext, a questo punto e’ in grado di
trovare la chiave utilizzata per cifrare. Se il mittente spedirà altri messaggi
usando la stessa chiave di cifratura, l’attaccante sarà in grado di decifrarli tutti.

3) CHOSEN PLAINTEXT: L’attaccante ha a disposizione il ciphertext e


l’algoritmo usato per cifrare, a questo punto sceglie dei plaintext ad oc per
vedere che tipo di output danno in modo tale da trovare alcuni pezzi della
chiave.

4) CHOSEN CIPHERTEXT: E’ come il chosen plaintext solo che eseguito con il


ciphertext.

TIPOLOGIE DI ALGORITMI:

1) ALGORITMI SIMMETRICI: Sono algoritmi che utilizzano la stessa chiave sia


per cifrare e per decifrare ove entrambi gli attori conoscono la medesima chiave
(es. DES, AES). Capita che la chiave di cifratura sia condividisa e che quella di
decifratura sia facilmente deducibile da questa.

2) ALGORITMI ASIMMETRICI: Sono algoritmi che utilizzano chiavi diversi per


la cifratura e la decifratura, ove entrambi posseggono rispettivamente una
chiave di cifratura ed una di decifratura (es. RSA). E' impossibile dedurre la
chiave di decifratura da quella di cifratura.
CIFRARI STORICI
1) CESARE:

Cifrario usato da Cesare per spedire i propri messaggi privati, consisteva nello
shiftare a dx o sx ogni lettera dell’alfabeto di un numero di cifre prefissato k.

Per cifrare:
y = x + k mod 26

k = {0, …, 25} che è lo spostamento per un totale di 26 caratteri

Per decifrare :
x = y – k mod 26

ATTACCHIAMO IL CIFRARIO:

1) C-ONLY: L’alfabeto ha 26 lettere e quindi un totale di 26 k diverse. Un


attacco a forza bruta sarebbe particolarmente efficace contro questo cifrario
dovendo controllare al più 26 chiavi.

2) KNOWN PLAINTEXT: L’attaccante ha a disposizione il ciphertext e


successivamente il plaintext, a questo punto è facile risalire alla chiave k. Se il
mittente userà la stessa chiave più volte, l’attaccante potrà decifrare tutti i
messaggi che passano sul canale.

3) CHOSEN CIPHERTEXT: L’attaccante sceglie come ciphertext un testo di sole


A e ottiene cosi la negazione della chiave (0=x+k).

4) CHOSEN PLAINTEXT: Viene scelto anche qui un particolare plaintext per


vedere che risultato da.

2) CIFRARI AFFINI:

Per cifrare si scelgono un α ed un β in modo che MCD(α, 26) = 1, perché se non


è verificato l'MCD non posso decifrare in quanto non esisterebbe l'inverso di α in
mod 26:

y = αx + β mod 26

α={1,…25}; β={0,…25};
α≠0 perché seno’ sarebbe uguale a Cesare.
E’ un’evoluzione del cifrario di Cesare, viene scelto un valore per α, β invece del
solo k.

Per decifrare ho bisogno di calcolare l'inverso di α in mod 26 (verificato prima


tramite il controllo del MCD(α, 26) = 1. Una volta fatto ciò devo calcolare quel
numero che moltiplicato per α mi da 1 mod 26. Una volta trovato l'inverso,
decifro in questo modo:

x = (y – β) * α-1 mod 26

ATTACCHIAMO IL CIFRARIO:

Prima di eseguire un attacco chiediamoci quanto sono le chiavi totali? Siccome il


mittente sceglie due incognite α, β verrebbe da dire che il numero totale di
chiavi sia k=25 * 26 = 650.

Se guardiamo bene la formula per la decifratura ci accorgiamo che impone il


calcolo dell’inverso di α, per cui dobbiamo scegliere α in modo tale che
ammetta inverso altrimenti nemmeno il destinatario sarà in grado di decifrare il
messaggio.

Quali scelte di α non vanno bene? Bisogna scartare tutti gli α che hanno un MCD
o GCD (great common divisor) con 26 ≠ 1 quindi tutti i numeri pari da 0 a 26 e il
numero 13. Il numero totale di chiavi è quindi 12 * 26 = 312.
POLIALFABETICI A SOSTITUZIONE
1) QUADRATO DI VIGENERE:

Si costruisce scrivendo l’alfabeto tante volte shiftando le lettere a sx di un


fattore k = {1, …, 25}.

Per cifrare abbiamo bisogno del messaggio m e di una chiave k.


Scriviamo il messaggio su una riga e la chiave sulla riga sotto incolonnando le
lettere, se la chiave è più corta del messaggio la si ripete tante volte fino a
quando non si raggiunge la lunghezza del messaggio.
La prima riga del quadrato verrà usata per le lettere del messaggio e la prima
colonna per le lettere della chiave, facendo l’intersezione riga-colonna si ottiene
la lettera del ciphertext.

Per attaccare questo cifrario, se il messaggio è abbastanza lungo si può


controllare le lettere che si ripetono in modo tale da trovare la lunghezza della
chiave (si utilizza la frequenza delle lettere in base al linguaggio scelto).

2) QUADRATO DI POLIBIO:

Il quadrato di Polibio ha un funzionamento analogo al quadrato di Vigenere, con


la differenza che le lettere dell’alfabeto sono distribuite su una matrice 5x5 e
per ogni lettera del messaggio si prendono i due simboli della colonna e della
riga corrispondenti.
Es. A = 11, B = 21, C = 31….

3) QUADRATO DI PLAYFAIR:

Anche questo quadrato è una variante del quadrato di Polibio in particola nella
matrice 5x5 viene inserita prima la chiave scelta e nelle caselle rimanenti le
altre lettere in ordine alfabetico che non compaiono però tra quelle della
chiave.

4) ADFGX:

Trattasi di un altro cifrario quadrato simile a quello di Polibio. La tecnica consiste


nel costruire un quadrato composto dall'intero alfabeto ripetuto una sola volta
ma mescolato (quindi le lettere risultano in ordine apparentemente casuale
anche se il loro susseguirsi è dato da una certa chiave prestabilita); ogni riga è
lunga quanto la parola ADFGX, idem ogni colonna; poiché non tutte le lettere
dell'alfabeto possono rientrare nello schema si è scelto di mappare le lettere I e
J con lo stesso carattere.
Di seguito un esempio di un ipotetico quadrato:
Il testo cifrato è costituito dalla coppia corrispondente al carattere da cifrare.
Per esempio, la parola ARMADIO è cifrata con il crittogramma

FF DX GA FF GD GG DF con, per esempio, A = FF.

Usato principalmente dai tedeschi nella Prima Guerra Mondiale ha tuttavia un


difetto: i crittotesti si ricavano dai caratteri, presi uno ad uno, del messaggio in
chiaro.

5) CIFRARIO DI HILL:

Si tratta del cifrario a blocchi per eccellenza, utilizza una matrice di numeri
come chiave ed un vettore come messaggio in chiaro. Si noti che la matrice è
scelta in maniera puramente casuale.

Il crittotesto è ottenuto mediante la moltiplicazione del vettore, che è il


messaggio in chiaro, con l'intera matrice che è la chiave di cifratura. La
moltiplicazione avviene, ovviamente, riga per colonna.

Es. il messaggio da criptare è il vettore [2, 0, 19] che corrisponde a [C, A, S]. Il
risultato del prodotto viene poi convertito in mod 26.

Per decifrare il crittotesto è sufficiente trovare l'inversa della matrice


precedente e ripetere la moltiplicazione.

6) OTP (One Time Pad)

Cifrario Utilizzato durante la Guerra Fredda.


E’ un stringa di bit semicasuali che veniva xorata bit a bit con il messaggio in
chiaro per ottenere il crittotesto.
La sconvenienza stava nel generare la chiave lunga quanto il messaggio e
trasferirla. L’altro problema riguarda la pseudocasualita’ della stringa generata,
non vengono generati numeri casuali ma pseudocasuali che dopo un tot di
iterazioni si ripetono, trovato il seme per generare la pseudosequenza
trovata la criticita’ al sistema.

Infine i buoni sistemi crittografici dell’era moderna devono avere due proprieta’
importanti (Claude Shannon):

1) DIFFUSION : Le modifiche che vado a fare su un bit o numero del messaggio


mi portano a fare grossi cambiamenti sul crittotesto.

2) CONFUSION : Ogni carattere del plaintext non deve dipendere direttamente


da un solo carattere del crittotesto ma da molti caratteri del plaintext.
DATA ENCRYPTION STANDARD (DES)
DES Nasce nel 1973 perché il NATIONAL BUREAU STANDARD oggi NIST aveva indetto
una gara per creare un nuovo sistema crittografico. IBM nel 1974 propone il suo
cifrario Lucifer e lo sottopone agli esperti del NIST. Il NIST accetta il cifrario ma ne
impone la modifica di alcune parti (decise dall'NSA) e cosi nel 1975 nasce DES.

DES è stato utilizzato largamente per tutti gli anni ’80 perché ritenuto sicuro fino al
1990 quando Shamir e Biham mostrarono che il sistema era attaccabile in maniera
intelligente e questo segnò l’inizio della fine per DES. Con la potenza di calcolo
disponibile nel 2012 DES è attaccabile via forza bruta.

I pro di DES risiedono nella sua velocità di esecuzione e la sua sicurezza (tant'è che
viene usato ancora oggi nell'e-commerce).
I contro del sistema erano rappresentati dalle modifiche apportate dalla NSA e dal
fatto che possedeva una chiave relativamente troppo corta.

DES è un cifrario FEISTEL cioè lavora su metà dei dati alla volta.

1) FUNZIONAMENTO GENERALE:

DES è formato da 16 round che si ripetono. Ogni round lavora su metà del
messaggio in chiaro (la metà destra o la metà sinistra a seconda del round e
della circostanza). Questi round sono detti Feistel Round a causa della
funzione (la funzione Feistel) che ad ogni round si vede applicata al messaggio.

1) In input DES vuole un plaintext lungo 64 bit. Anche la chiave è lunga 64 bit
dei quali 56 bit sono costituiti dalla password vera e propria ed i rimanenti 8 bit
sono bit cosiddetti di parità. Nella pratica ho 2^56 chiavi totali tra cui scegliere
ma non tutte sono forti alla stessa maniera.

2) In DES i 64 bit del plaintext vengono permutati tramite una permutazione


iniziale, in questo primo passo dell'algoritmo, sempre nello stesso modo
seguendo uno schema pre determinato. Tale permutazione preliminare ha un
chiaro significato crittografico permettendo così di ridurre le probabilità di
effettuare sull'algoritmo un certo tipo di attacco.

3) A questo punto i 64 bit “rimescolati” entrano nel primo dei 16 round:


Round nel dettaglio:

1) Ogni round ha in input di 64bit che viene diviso in due parti dx32bit e
sx32bit

2) La parte dx32bit entra in una funzione feistel insieme alla chiave del
round a 48bit

3) L’output a 32bit ottenuto viene xorato con la parte sx32bit e andrà a


comporre cosi la parte dx32bit del round successivo

4) La parte dx32bit viene anche mandata direttamente nella parte


sx32bit del round successivo.

Calcolo chiave del round:

La chiave di DES è a 64bit però per eseguire le operazioni all’interno del


round dobbiamo portarla a 48bit, vediamo come fare:

1) 64bit= 8byte, ogni byte ha 1bit di controllo e non viene utilizzato


quindi 64bit-8bit controllo=56bit

2) Questi 56bit vengono divisi in due blocchi sx28bit e dx28bit

3) I bit delle due parti vengono shiftati a sinistra di 1 0 2 bit a seconda del
round in cui mi trovo

4) Riunisco le due parti e attraverso una tabella eseguo la selezione di


48bit prefissati

Funzione feistel in dettaglio:

1) In input come visto in precedenza viene passata la parte dx32bit del


round precedente

2) Attraverso una funzione di espansione, una particolare tabella che


indica quali bit raddoppiare e in che posizione metterli, si passa dai 32bit
ai 48bit

3) Viene eseguito lo XOR con i 48bit della chiave

4) 48bit = 8 blocchi da 6bit (b0,b1,b2,b3,b4,b5)


5) A questo punto il risultato dello XOR diviso in blocchi da 6 bit deve
entrare nell’ S-Box del round S-i

6) I bit b1 e b5 individuano la riga dell’S-Box mentre gli altri quattro bit


individuano la colonna. Si fa l’intersezione riga-colonna e si prende il
contenuto della casella dell’S-Box (numero da 0 a 15) che è rappresentato
come una sequenza di 4bit

7) Facendo questa operazione per tutti e 8 i round otteniamo 8 blocchi da


4bit = 32bit

8) Con una tabella apposita scambio l’odine di questi 32bit ed ottengo il


risultato della funzione feistel

Tutto questo si ripete per 16 volte consecutive.

Si è scelto di ripetere i round 16 volte perché ripeterli un numero inferiore di


volte vorrebbe dire compromettere l'integrità del crittogramma esponendolo a
certe vulnerabilità.

4) Una volta ottenuto l'output dei 16 round viene eseguita una permutazione
inversa che darà come output il crittotesto a 64 bit.

E' possibile decriptare il crittotesto ottenuto seguendo lo schema di DES


partendo dall'ultimo round all'inverso. La chiave, dopotutto, è custodita sia dal
mittente che dal destinatario.

Uno degli svantaggi di DES è che per criptare lavora solo con metà del
messaggio alla volta, andando così contro il principio di Kirchoff.

Cosa aveva fatto modificare il NIST? Il NIST aveva imposto l’introduzione degli
S-Box che erano tenuti segreti. L’attacco di Biham e Shamir si basa proprio sulla
debolezza di questi S-Box conoscendo i quali si riuscì ad attaccare il sistema.

2) ATTACCHI A DES:

Ce ne sono principalmente di due tipi.

2.1) Crittoanalisi differenziale:

Tutti i cifrari che lavorano su una sola porzione del testo alla volta sono
detti cifrari Feistel.

Si sceglie un messaggio in chiaro con una parte fissa e, dandolo in pasto


all'algoritmo, si guarda cosa si è ottenuto.

Lo si confronta poi con altri messaggi con parte fissa. Risalendo a ritroso
nel processo di criptazione ci si rende conto che nel momento dello XOR è
possibile ricavare una parte della password usata dalla funzione Feistel
durante la cifratura. Di messaggio in messaggio si riesce a collezionare
man mano una certa quantità di “parti di chiave”. La chiave sarà
quindi data da quei bit che si ripetono più spesso tra tutti quelli
collezionati.
Questo attacco funziona quando si ha a disposizione una certa
quantità di messaggi in chiaro da dare in pasto all'algoritmo.

2.2) Crittoanalisi lineare:

Scelgo il messaggio in chiaro in modo che si trovi in un intorno del


crittotesto.

Esiste allora una funzione lineare che mi assicura che da una x del
dominio di DES si arrivi ad una y nel suo codominio, dove il dominio
contiene i messaggi in chiaro ed il codominio quelli criptati. Questa
funzione può non portarmi esattamente a y partendo da x, ma
sicuramente in un intorno (matematico) di y. Di conseguenza mi trovo
anche nell'intorno della chiave usata per criptare il messaggio.

Si tratta di un metodo probabilistico con una funzione lineare.

3) MODALITA’ OPERATIVE DI DES

Fino ad ora abbiamo schematizzato l'utilizzo dell'algoritmo generico di DES, ma


a livello pratico le modalità di utilizzo di questo sistema crittografico è la stessa
degli algoritmi di cifratura di tipo simmetrico.

Le modalità di utilizzo di DES sono principalmente 5.

3.1) ECB (electronic codebook)

Di tipo simmetrico a blocchi. Si prende il testo in entrata, lo si divide in


blocchi da 64 bit ciascuno e, un blocco alla volta, lo cripto con un unica
chiave. Se il plaintext non è un multiplo di 64 devo aggiungere padding.

Contro: l'attaccante può sapere che la chiave che si usa per criptare è
sempre la stessa. La si può quindi ricavare utilizzando, per esempio, un
dizionario per campionare tutte le ripetizioni nel crittotesto così da
collezionare le parti della chiave al fine di comporla interamente.
3.2) CBC (cipher block chaining)

Di tipo simmetrico a blocchi. Si divide il messaggio in chiaro in blocchi


di 64 bit e si prende il primo blocco per poi XORarlo con del “rumore” per
poi darne il risultato in pasto all'algoritmo di DES; così si ottiene il primo
blocco del crittotesto.

Il secondo blocco del messaggio originale è XORato invece con il primo


blocco di crittotesto e ciò che si ottiene come secondo blocco criptato
andrà in XOR con il terzo blocco del messaggio in chiaro e così via.

In questa maniera i blocchi non sono più strutturalmente identici, si


cifrano con componenti diverse e non basta sapere la chiave usata da
DES per decrittarli.

Il “rumore” in realtà è un vettore di inizializzazione (detto anche IV)


contenente un numero casuale che è comunicato e criptato tramite DES
in modalità ECB (vedi sopra) previo accordo tra le due parti.

Per cifrare e decifrare il blocco j-esimo si concretizza nella pratica


l'espressione:

CIFRARE: CJ = EK(PJ xor CJ-1)

DECIFRARE: PJ = DK(CJ) xor CJ-1

3.3) CFB (cipher feedback)

Ti modalità a flusso e non a blocchi. Cripta un carattere del


messaggio in chiaro alla volta.
Si utilizza in questo caso un registro di inizializzazione che, criptato con
una chiave, ottiene un registro cifrato del quale si vanno a prendere gli 8
bit più significativi per andarli a XORare con i primi 8 bit del testo.
In seguito si prenderà un secondo registro (corrispondente al primo
registro ma shiftato di 8 bit) e per riempire gli 8 bit vuoti a destra di
questo nuovo registro inserisco il crittotesto ottenuto al passo
precedente.

Contro. Se durante la fase di cifratura si ottiene una distorsione,


saranno distorti anche tutti i futuri procedimenti di cifratura per
quanto riguarda il resto del messaggio. L'errore quindi tenderà a
propagarsi ed a danneggiare tutto il procedimento, anche se si tratta
comunque di una propagazione limitata: al secondo passaggio, infatti,
l'errore si corregge automaticamente ed all'interno del crittotesto si ha un
solo blocco corrotto.

Per cifrare e decifrare il flusso j-esimo si concretizza nella pratica


l'espressione:

CIFRARE: OJ=L8(EK(XJ))
CJ=PJ xor OJ
XJ+1=L8(XJ) || CJ

DECIFRARE: PJ=CJ xor L8(EK(XJ))

3.4) OFB (output feedback)

È un metodo che riesce a risolvere il problema dell'errore di trasmissione.


Identico in tutto alla modalità precedentemente descritta, salvo per il
fatto che si limita ad eseguire il procedimento in locale, tralasciando la
comunicazione sul canale.

I registri sono determinati localmente da dati locali provenienti dalla


creazione del registro precedente. Al massimo ci si sbaglia a criptare
C 1 ma non si propaga nessun errore allo step successivo.
Pro: non propaga l'errore ed è nettamente più veloce in fase di
precompilazione.
Contro: non è un meccanismo parallelizzabile.

3.5) CTR (counter)

Contrariamente a quanto detto per OFB, questo meccanismo è


parallelizzabile.

Il secondo registro è composto dal primo registro più 1: in questa maniera


posso cifrare in parallelo ogni carattere del testo. Quando il counter del
registro raggiunge la sua cifra massima si azzera e riprende a contare da
1.

4) DOPPIO E TRIPLO DES

Nel 1998 la RSI lanciò un nuovo bando per dimostrare che il tempo che serviva
per decrittare un messaggio in DES era sempre meno ogni anno che passava il
vincitore di tale bando dimostrò tranquillamente che DES era attaccabile in
meno di un mese. Così, in seguito a questa presa di coscienza, si volle costruire
un hardware specifico per riuscire ad attaccare DES in meno di 4 giorni.

DES tuttavia è ancora utilizzato in due modalità differenti:

4.1) Doppio DES. Questa variante di DES prende in entrata un testo e lo cifra
con l'utilizzo di due chavi completamente differenti tra loro seguendo la formula:

C2 = Ek2 ( Ek1 (m))

4.2) Triplo DES. In questa modalità di DES il testo in chiaro viene criptato con
una password, decriptato con una seconda password e criptato ancora con la
prima password; la formula che descrive il procedimento è:

C3 = Ek1 ( Dk2 ( Ek1 (m)))

L'attacco a doppio DES modifica la complessità computazionale da 2^57 a


2^56 . Per questo ed altri motivi il doppio DES ha avuto vita breve ed è stato
accantonato molto in fretta. Per quanto riguarda triplo DES, cifrare e decifrare
significa sempre spostare dei bit o a destra o a sinistra. Il concetto è infatti
sfruttare lo stesso meccanismo del DES semplice con 2^112 forza
computazionale.
ADVANCED ENCRYPTION STANDARD (AES)
Nel 1997 il NIST indette una nuova gara per trovare il successore di DES dichiarato
ormai vulnerabile. Il nuovo algoritmo doveva avere diverse caratteristiche tra cui
supportare chiave di 128, 192, 256 bit e lavorare su blocchi di 128bit. Alla fine il
vincitore fu Rijndael.

L’ALGORITMO DI BASE:

Come chiesto anche dal NIST, AES lavora con chiavi di lunghezza variabile che
determinano la lunghezza delle operazioni svolte, infatti, con una chiave di
128bit vengono eseguiti 10 round, con una di 192bit vengono eseguiti 12 round
mentre con 256bit di chiave si eseguono 14 round.

L’algoritmo si compone di quattro step chiamati LAYERS.

1) THE BYTESUB TRANSFORMATION


2) THE SHIFTROW TRANSFORMATION
3) THE MIXCOLUMN TRANSFORMATION
4) ADDROUNDKEY

Concentriamoci sull’encryption, in particolare quella di AES a 128bit, dove


vengono eseguiti 10 round.

1) Il processo di encrypt e’ eseguito in 3 parti:

1) Round iniziale: ARK (add roundkey) con la chiave k0

2) Seguono nove round di SB (subBytes), SR (shiftrows), MC


(mixcolumn) e ARK con le chiavi da k1-9

3) Un round finale SB, SR, ARK con la chiave k10.


I LAYERS IN DETTAGLIO:

Come prima cosa i 128bit vengono divisi in 16 gruppi da 8bit ciascuno.


Questi gruppi vengono messi in una matrice 4x4.

BYTESUB (SUBBYTE):

Con questa operazione si lavora con l’S-Box di AES che è una matrice 16x16.

Prendo gli 8bit di input (uno dei gruppi di cui sopra ) e utilizzo i primi 4bit e gli
ultimi 4bit per individuare rispettivamente la riga e la colonna dell’S-Box

Facendo l’intersezione riga-colonna si prende il numero corrispondente, lo si


converte in binario e si ottiene il nuovo gruppo di 8bit che verrà sostituito a
quello in input

L’operazione è eseguita per tutti i gruppi fino ad ottenere una nuova matrice
4x4

SHIFTROWS:

Durante questa fase vengono shiftate le righe della matrice a sx di 0-1-2-3


posizioni a seconda del numero di riga. (es. la riga zero rimane invariata, la riga
1 viene shiftata di 1 pos a sx…).

Si ottiene cosi una nuova matrice 4x4 con alcuni elementi shiftati.

MIXCOLUMN:

Prendiamo ora in input ancora la nostra matrice 4x4 che ha già subito tutte le
operazioni precedenti , moltiplichiamo ogni colonna con ogni colonna di una
matrice prefissata fino ad ottenere una nuova matrice 4x4.

ADDROUNDKEY:

L’ultima fase prende ancora una volta la matrice 4x4 e fa lo XOR con la chiave
del round, anch’essa organizzata come una matrice. (colonna x colonna).

Tutti i layers vengono eseguiti 9 volte perché stiamo prendendo in


considerazione input di 128bit.

CHIAVE DEL ROUND:

In questa parte vediamo come Rijndael calcola la chiave da 128bit per ogni
round.

Tutto parte dalla chiave iniziale a 128bit che viene divisa in 16 blocchi da 8bit
ed organizzata come una matrice 4x4.
1) Si prende l’ultima colonna della matrice e si shiftano gli elementi verso
l’alto di 1byte

2) Con l’ultima colonna cosi shiftata faccio il SubByte con l’S-Box e ottengo cosi
una nuova colonna

3) Prendendo nuovamente come input quest’ultima colonna se ne esegue lo


XOR con una colonna costante e lo XOR con la prima colonna della matrice. Si
ottiene cosi la prima colonna della chiave

4) Le altre 3 colonne della chiave si ottengono

5) Si prende la prima colonna della chiave e si fa lo XOR con la seconda


colonna della matrice iniziale e si ottiene la seconda colonna della chiave

6) Si prende la colonna cosi generata (seconda colonna della chiave) e si


fa lo XOR con la terza colonna della matrice iniziale ottenendo la terza
colonna della chiave

7) Infine, analogamente si prende la terza colonna della chiave si fa lo


XOR con la quarta colonna della matrice iniziale e si ottiene la quarta
colonna della chiave

2) I layers BS,SR,MC,ARK, sono tutti invertibili:

2.1) L’inverso di BS è un’altra tabella chiamata InverseByteSub

2.2) L’inverso di SR si ottiene shiftando le righe a dx rispettivamente di 0,


1, 2, 3 posizioni

2.3) L’inverso di MC esiste perché la matrice usata nella moltiplicazione è


invertibile

2.4) Anche ARK ha il suo inverso

Il processo di decryption e’ eseguito anch'esso in 3 parti all'inverso

1) Round iniziale: ARK usando la chiave k10

2) Seguono Nove round con di IBS, ISR, IMC, IARK usando le chiavi da k 9-1

3) Un round finale IBS, ISR, ARK con la chiave k0

Notare che nel primo e nell’ultimo passaggio si esegue ARK e non IARK.

AES è uno standard utilizzato dal 2002 per criptare grandi flussi di dati. Al momento
(fine 2012) non è ancora stato attaccato salvo in maniera teorica attraverso dei
presupposti assurdi.
Sistemi crittografici simmetrici e asimmetrici
Per intenderci, nei sistemi crittografici simmetrici servivano, dove N è il numero
degli attori:

(N – (N – 1)) / 2 chiavi

Per fare un esempio, se gli attori fossero stati 10 (N = 10), allora avremmo dovuto
lavorare con:

N! / (N – 2) ! 2! ovvero 10! / 8! * 2! = 10 * 9 / 2 = 45 chiavi

Nei sistemi crittografici asimmetrici, invece, ogni attore possiede tante chiavi
quanti sono gli attori complessivi della comunicazione.

Per fare un esempio, il singolo attore possiede la sua chiave privata più tutte le chiavi
pubbliche degli altri attori.

Funzione One Way


La funzione one way è un tipo di procedura chiaramente a “senso unico”.
Nel dominio di questa funzione, come accade per ogni funzione di cifratura, si trovano
i testi in chiaro e nel suo codominio i testi cifrati, tuttavia una funzione one way
consente solamente il passaggio da testo in chiaro a testo cifrato senza permettere la
reversibilità del procedimento.

Una funzione di definisce One Way se:

E' facile, dato x, calcolare y = f(x) ma è difficile, dato y, calcolare f(x) = y

Difatti, prendiamo in esame:

1) RSA: calcolare il prodotto di due numeri gradi è semplice.


Calcolare i due fattori, cioè fattorizzare un numero grande è difficile.
2) Logaritmo discreto: calcolare l'elevamento a potenza di numeri grandi è facile.
Calcolare il logaritmo discreto è invece difficile.

Tale impossibilità deriva dalla sua complessità computazionale che è indicata


propriamente come complessità computazionalmente intrattabile da un punto di
vista matematico, così che non sia possibile risalire al testo in chiaro in un tempo utile
(non è impossibile risalire al testo in chiaro ma ci vorrebbe così tanto tempo, in termini
di anni nell'ordine di migliaia di milioni, da scoraggiare chiunque nel tentare) da parte
di un attaccante.

L'unica maniera in cui una funzione one way può essere resa reversibile è inserire in
essa una trap door così da forzare la sua complessità intrattabile. Ovviamente le trap
doors sono e devono rimanere segrete.
Rivest, Shamir, Adleman (RSA)
RSA rappresenta un esempio di cifrario asimmetrico tra i più diffusi al mondo. Prende il
nome dai suoi ideatori, Diffie e Hellman, che lo hanno ipotizzato nel 1976.
RSA è un esempio di sistema asimmetrico che utilizza una funzione One Way con Trap
Door che implementa nella pratica la moltiplicazione tra numeri composti da un
numero abbastanza grande di cifre.

FUNZIONAMENTO GENERALE:

Poniamo il caso che Alice voglia mandare un messaggio a Bob.

1) Bob sceglie due numeri naturali, interi e primi p, q abbastanza grandi a


piacere, li si moltiplica e calcola:

n=p*q

2) Bob sceglie un’esponente numero naturale e primo e (< 100.000), scelto in


modo tale che:

GCD(e, (p – 1) * (q – 1)) = 1

dove si applica il piccolo teorema di Fermat esteso da Eulero:

((p-1) * (q-1)) = φ(n) di di Eulero

3) Bob calcola d in base al parametro e scelto tramite l'algoritmo di Euclide


esteso in modo tale che:

d * e ≡ 1 mod((p-1) * (q-1))

ovvero che d sia l'inverso di e in

mod((p-1) * (q-1))

4) Bob spedisce ad Alice i parametri n ed e, ovvero la chiave pubblica:

PUB(n, e) di Bob

e tiene segreti i parametri p, q, d, ovvero la chiave privata:

PRIV(p, q, d) di Bob

5) Alice cifra il messaggio tramite il teorema cinese dei resti usando la


chiave pubblica di Bob:

C ≡ me (mod n)

e lo spedisce a Bob

6) Bob decifra il messaggio tramite il teorema cinese dei resti usando la


chiave privata di Bob facendo:
m ≡ Cd(mod n)

e legge in messaggio di Alice.

Quindi riassumiamo i parametri di RSA:

DIMOSTRAZIONE RSA:

Si vuole dimostra che (me )d ≡ m (mod n)

Ovvero che cifrando il messaggio e decifrando il crittotesto, si riottiene il messaggio


originale.
Dimostro:

1) Per la proprietà degli esponenti:

(me )d = m e*d

2) Gli esponenti invece possiamo scriverli come:

e * d ≡ 1 mod(p-1) * (q-1)

che si possono riscrivere come:

e * d = k * [(p-1) * (q-1)] + 1

di conseguenza vale che:

e*d
m ≡ m mod n

e che quindi:

k * [(p-1) * (q-1)] + 1
m ≡ m mod n
Adesso bisogna dimostrare che la congruenza vale sia per mod p, mod q e
per mod n. Se dimostro questo, allora la dimostrazione è valida.

I casi p e q, si dividono rispettivamente in due sottocasi:

1) p non coprimo con il messaggio m, ovvero GCD(p, m) ≠ 1

se GCD(p, m) ≠ 1 significa che p e m hanno un fattore in comune (è p) perché p è un


numero primo, di conseguenza p divide p, p divide m.

Se p divide m allora:

m ≡ 0 mod p

in quanto m mod p = 0. Di conseguenza qualunque esponente k do ad m, mi darà


sempre:

m k ≡ 0 mod p

di conseguenza vale che:

k * [(p-1) * (q-1)] + 1
m ≡ 0 mod p

di conseguenza poiché:

k * [(p-1) * (q-1)] + 1 e*d


m =m

allora qualunque e, d scelgo sarà sempre:

e*d k * [(p-1) * (q-1)] + 1


m =m ≡ 0 mod p

poiché scrivere congruo a 0 mod p è uguale a scrivere congruo a m mod p, allora


possiamo affermare che:

e*d k * [(p-1) * (q-1)] + 1


m =m ≡ m mod p

2) p coprimo con il messaggio m, ovvero GCD(p, m) = 1

se GCD(p, m) = 1 significa che p ed m non hanno fattori in comune. Utilizzo il teorema


dei numeri coprimi. Se prendo due numeri coprimi p ed m, per il Teorema vale che
GCD(p, m) = 1, allora vale che:

(p-1)
m ≡ 1 mod p

k * [(p-1) * (q-1)] + 1
riprendendo la formula iniziale m la riscrivo in questo modo:

k * [(p-1) * (q-1)] + 1 (p-1) * k * (q-1)]


m = ((m ) ) * m mod p
poiché:

(p-1)
m = 1 mod p

allora la formula sopra diventa:

k * [(p-1) * (q-1)] + 1 (p-1) * k * (q-1)] * k * (q-1)]


m = ((m ) ) * m = ((1) ) * m mod p

allora vale che:

* k * (q-1)]
((1) ) * m = m mod p

di conseguenza vale che:

e*d k * [(p-1) * (q-1)] + 1


m =m ≡ m mod p

3) q non coprimo con il messaggio m, ovvero GCD(q, m) ≠ 1

Si fa del tutto analogo al caso:

p non coprimo con il messaggio m, ovvero GCD(p, m) ≠ 1

ottenendo lo stesso risultato.

4) q coprimo con con il messaggio m, ovvero GCD(q, m) = 1


Si fa del tutto analogo al caso:

p coprimo con con il messaggio m, ovvero GCD(p, m) = 1

ottenendo lo stesso risultato.

5) Caso n, ovvero p * q

Fatto ciò, abbiamo visto i due punti sia per p che per q. Ora dal momento che p e q
sono primi, allora:

k * [(p-1) * (q-1)] + 1
m ≡ m mod n

quindi vale che:

k * [(p-1) * (q-1)] + 1
m - m ≡ 0 mod n

Poiché tutta la parte di sinistra è divisibile sia per p che per q, allora possiamo scrivere
in questo modo:

k * [(p-1) * (q-1)] + 1
m = p * k1
k * [(p-1) * (q-1)] + 1
m = q * k2
ma dato che p non divide q e q non divide p, posso scrivere:

k * [(p-1) * (q-1)] + 1
m = p * q * k3

Ma p * q è esattamente n = p * q, di conseguenza vale che:

n * k3 ≡ 0 mod p

Ne deriva quindi che:

k * [(p-1) * (q-1)] + 1
m ≡ 0 mod n

e che quindi:

e*d
m ≡ m mod n

TEOREMI MATEMATICI DI RSA:

Dietro l'algoritmo di RSA si nascondono diversi algoritmi e diverse


basi matematiche.

1) La scelta dei numeri primi:

Come è già stato reso noto, RSA fa uso tra le altre cose di due numeri primi p e
q sufficientemente grandi.

Li sceglieremo di almeno 100 cifre, così da essere sicuri che si tratti di numeri
molto alti. Ora, scegliendo un numero a caso cosiffatto, voglio sapere che
probabilità ho di averne scelto davvero uno primo.

Si esprime il concetto di “numero primo con 100 cifre” come π (100).

Ma quanti sono questi π (100)? Sono molti? Sono pochi? Esiste una formula
matematica che ne calcola il numero esatto.

La stima va fatta su π (100) - π (99) per eliminare dal conteggio tutti gli
eventuali numeri primi con 99 cifre o meno. Dopotutto voglio contare solamente
i numeri primi con 100 cifre.

La formula da applicare è:

x = x / ln (x)

in questa maniera:

π (100) - π (99) = [10 100 / ln (10 100 )] – [10 99 /ln (10 99 )] = 4*10 97
Più il conteggio delle cifre di p e q è alto minore è la probabilità di un attacco a
forza bruta con effettivo successo.

2) Fattorizzazione:

Come posso fattorizzare numeri primi molto grandi? Solitamente si parte dal più
piccolo numero primo e lo si divide per ogni sottomultiplo in maniera
sistematica e consecutiva.

Per esempio posso scomporre il numero 576 in 2 6 *3 2 e 135 in 5*3 3 , ecc.

Ma posso farlo anche con n? Il problema è dato dal tempo di cui disponiamo.
Fattorizzare un numero grande come il numero primo n conduce ad un problema
computazionalmente intrattabile.

3) Algoritmo di Euclide:

Anche per calcolare l'MCD o GCD devo fattorizzare.

Se devo calcolare il MCD (a, b) prendo

a = b * q1 + r1

ovvero a uguale a b moltiplicato per un quoziente più il suo resto, con b il


numero più piccolo possibile.

Al secondo passo al posto di a metto b e ripeto il calcolo:

b = r 1 * q 2 + r2

e via così fino al passo:

rk-1 = rk * qk+1 + 0

e abbiamo trovato ciò che cercavamo, ovvero:

rk = GCD tra a e b

L'MCD finale è costituito da rk ovvero dal resto al penultimo passaggio


dell'algoritmo di Euclide.

4) Algoritmo di Euclide esteso:

Costituisce una riscrittura dell'algoritmo di Euclide tradizionale. Si vuole trovare


il MCD (a, b) = d con a e b diversi da 0; allora esistono sicuramente x ed y
diversi da 0 tali che:

x*a+y*b=d
Se a e b sono coprimi, MCD (a,b) = 1, allora x * a +y * b = 1

Calcolare l'inverso ci aiuta in questo compito. Di solito si calcola l'inverso in


questa maniera:

Se GCD(a,b) = 1 => sono coprimi =>

x * a + y * b = 1 => x * a ≡ 1 (mod n) e x è l’inverso di a.

L'algoritmo esteso di Euclide permette di calcolare l'inverso di un qualsiasi


numero in maniera veloce ed immediata. Utilissimo quando si ha a che fare con
numeri molto grandi. a e n infatti sono numeri molto grandi. Controllo MCD (a,
n) con n = p * q ed a numero a caso. L'MCD dovrebbe essere uguale a 1, in caso
contrario sarà uguale a p o a q.

5) Proprietà delle convergenze

Quando il MCD (a,b) = 1 si può calcolare l'inverso di a, ma quando invece è


diverso da 1?

Si assume che a * x = b mod n con MCD (a,n) = d

Se a non è divisibile per b allora non esiste soluzione.


Se a è divisibile per b allora calcolo le soluzioni e ne troverò un intero
insieme, tutte possibili (e non esiste un solo inverso). Saranno tutte
del tipo:

x0, x0 + n/d, x0 + (2 n/d), …., x0 + (d – 1) * n/d

con d numero di inversi diversi. Si dimostra infatti che non è vero che se
MCD è diverso da 1 non esistono inversi.

6) Teorema cinese dei resti

Siano r1…n dei numeri naturali a due a due coprimi tra loro, ovvero
MCD(ri, rj) = 1 con i e j diversi per ogni i e j.

Posso scrivere allora n = r1 * r2

Allora esiste un intero x soluzione del sistema di congruenze:

x ≡ b mod n

che posso riscrivere come un sistema:

x ≡ a1 (mod r1)
x ≡ a2 (mod r2)

x ≡ a n (mod rn)

RSA utilizza questo teorema in questo modo:

m e = c mod n

che posso riscrivere come un sistema:

m e ≡ a1 (mod r1)
m e ≡ a2 (mod r2)

m e ≡ a n (mod rn)

In questo modo si fanno calcoli con numeri più piccoli. Usato per velocizzare le
operazioni di cifratura.

7) Piccolo teorema di Fermat

Se p è un numero primo abbastanza grande e MCD (a, p) = 1 con a scelto a


caso, allora:

p-1
a ≡ 1 mod p

Dal teorema di Fermat, si ha un'estensione di Eulero, ovvero:

Si prendono a ed n (Si prende un numero n a caso purchè sia primo) numeri


qualunque con MCD (a, n) = 1, allora:

a ^ Φ (n) ≡ 1 mod p

dove Φ (n) è la cosiddetta funzione di Eulero.

Applicando la funzione di Eulero a diversi casi, si ottengono diversi


risultati, tutti riassunti nella tabella seguente:
IMPLEMENTAZIONE SICURA DI RSA:

1) Radice quadrata di n:

Si generano p e q sufficientemente grandi e primi. Ma esattamente quali chiavi


scegliere da questa coppia proposta di p * q = n?

Il ragionamento dev'essere questo: p e q devono essere il più grande


possibile ed abbastanza distanti tra loro. Infatti chi opera un attacco a
forza bruta calcolerà le radici quadrate dei due n e cercherà p e q nell'intorno di
quel valore.

2) Calcolo di Φ (n):

Perché bisogna tenere segreti p, d e quindi anche φ(n)?


L’attaccante conosce n perché lo vede sul canale, ma se riesce a trovare anche
φ(n) può risalire a p, q in questo modo:

n – φ(n) + 1 = (p * q) – ((p – 1) * (q – 1)) + 1 = p + q

Ma poiché conosco n = p * q, vediamo come ricavare p e q:

ax2 - bx + c = 0

con a = 1, b = (p + q), c = n. A questo punto mi basta trovare il determinante


per trovare i singoli valori di p e q.

Questo significa che: non è necessario proteggere solo p e q, ma anche


n e Φ (n).

3) Porzioni di p, q e d:

Se si conosce anche solo il 50% di p oppure di q, si riesce ugualmente ad


attaccare il sistema.

È possibile anche con porzioni anche solo del 25% di d. Quest'attacco danneggia
il sistema in un tempo lineare.

RSA è un algoritmo potente tuttavia presenta delle caratteristiche sulle quali bisogna
riflettere come:

- Va implementato correttamente scegliendo dei valori opportuni altrimenti si


corre il rischio di comprometterne la sicurezza

- RSA è lento a cifrare per questo si cifra solo la chiave mentre il messaggio lo si
cifra usando un altro algoritmo
ATTACCHI AD RSA:

Vediamo ora alcuni attacchi al sistema che si basano appunto su una scorretta
implementazione dello stesso da parte del programmatore.

1) LOW EXPONENT ATTACKS:

Si può essere tentati di scegliere un’esponente piccolo per semplificare i conti e


raggiungere prestazioni migliori in cifratura e decifratura. Questo però porta al
problema che se:
d < 1/3 4√n

si può essere sotto attacco, per questo e deve essere sufficientemente


grande, per convenzione si prende il numero primo 2 16+1.

2) SHORT PLAINTEXT:

Abbiamo detto che RSA è lento e va usato per cifrare la chiave di un altro
algoritmo, il problema che può sorgere è che quando andiamo a cifrare qualcosa
di corto, l’attaccante può operare come segue per cercare di risalire a p o q.

1) L’attaccante si crea due liste:

una con cx-e (mod n) e l’altra con ye (mod n)

2) Se scorrendo queste liste ci sono due valori che coincidono può fare:

c ≡ (xy)e (mod n), dove xy=m

Quanto deve essere lunga la lista? Siccome p e q solitamente contengono la


metà delle cifre di n, la lista è sufficiente che sia lunga 2cifre di p oppure q.

Come ci si difende da questo attacco? Si prende il messaggio m e si aggiunge


un padding OAEP (optional asymmetric encryption padding) in modo da
allungare il plaintext e rendere impossibile prendere una lista abbastanza lunga.

3) TIME ATTACKS:

Questo è forse l’unico attacco non matematico apportato al sistema, si basa sui
tempi di decifratura dei bit.

Nel dettaglio, si controlla il tempo che ci mette l’algoritmo a decifrare una


determinata sequenza di 1 o 0.

Si calcola la varianza, che se è sopra una certa soglia vuol dire che c’è stato un
1, mentre se è sotto c’è stato uno 0. L’attacco è relativamente semplice però
funzionava, quindi bisogna in qualche modo difendersi.
Per fare ciò si moltiplica e divide ogni bit per lo stesso numero in modo da
lasciarlo invariato, ma da sballare i tempi di computazione rendendo impossibile
determinare il bit in ingresso.

PROBLEMATICHE IMPLEMENTATIVE DI RSA:

RSA impone di scegliere due numeri p e q primi sufficientemente grandi, ma scegliere


questi numeri non è facile come sembra, infatti nessuno di noi sa quali sono i numeri
primi con 200 cifre decimali, come fare allora?

1) PRINCIPIO FONDAMENTALE:

Questo algoritmo PROBABILISTICO ci viene in aiuto.


Come faccio a sapere se il numero n è un numero primo?

Prendiamo un numero a caso n e due numeri a caso x, y tali che:

x2≡ y2 (mod n) e x ≠ ±y (mod n)

se le due condizioni sono verificate allora n non è primo.


E’ possibile dimostrarlo infatti GCD(x-y, n) = p oppure a q
(difatti n = p * q).

Per fare ciò ci sono altri metodi, come ad esempio il MILLER-ROBIN,


SOLOVAY-STRASSEN.

2) FATTORIZZAZIONE DI FERMAT:

Parliamo ora delle tecniche di fattorizzazione. Posso scrivere:

n = i2 + j2 = (i + j) * (j – 1)

Prendo allora n e sommo ad esso una certa quantità b riconoscibile in i


oppure in j, elevo tutto al quadrato e controllo se si è ottenuta una radice
perfetta.
Se così accade, posso dire di aver fattorizzato correttamente il numero n.

3) CRIVELLO O SETACCIO QUADRATICO:

Supponiamo quindi di fattorizzare il numero n=3837523 che non ha


fattori vicini. Sfruttando l'idea di prima si vuole trovare x 2 ≡ y2 mod n
ma non avendo né x né y ne scelgo alcuni puramente a caso avendo
modo così di costruire le solite due liste. I casi sono due: o sono molto
fortunato e trovo subito i fattori che cerco oppure utilizzo il crivello
quadratico: può darsi che moltiplicando gli elementi di ogni lista tra
loro trovi sempre tra loro qualche congruenza.

Se è vero che y2 = x2 allora si può dire anche che MCD(x-y, n) = (p, q).
Problema del logaritmo discreto
LOGARITMO DISCRETO:

La funzione logaritmo è l'inverso della funzione esponenziale.

Fissato un numero primo p, siano a ed b due numeri interi non nulli in mod p,
tali che:

b ≡ ax mod p

allora:

loga(b) mod p = x

Quindi calcolare il logaritmo discreto significa calcolare x.

L'esponente x è chiamato logaritmo discreto di b per la base a in mod p, dove x


assume valori compresi fra:

0 <= x <= (p - 1)

Il risultato è una classe di congruenze.

LOGARITMO DISCRETO UNIVOCO:

Spesso a è una radice primitiva o generatore in mod p:

In questo caso, ogni b appartenente a 1, 2, 3, …, (p – 1) è una potenza di a


mod p. Quindi b rappresenta sempre una potenza distinta di a in quanto ogni
risultato è una classe, cioè identifica ognuno dei possibili valori numeri compresi
tra 1, 2, 3, …, (p – 1).
Se invece a non è un radice primitiva, allora il logaritmo discreto non sarà
definito per certi valori di b.

Infatti abbiamo ad esempio che a = 3 è una radice primitiva o generatore


in mod p = 7:

ax ≡ b mod p
========
31 = 3 mod 7
32 = 2 mod 7
33 = 6 mod 7
34 = 4 mod 7
35 = 5 mod 7
36 = 1 mod 7
Difatti si può notare come siano stati generati tutti i valori di b da 0 a 6, escluso
lo 0.

Diversamente, ad esempio a = 2 non è una radice primitiva o generatore


in mod p = 7:

ax ≡ b mod p
========
21 = 2 mod 7
22 = 4 mod 7
23 = 1 mod 7
24 = 2 mod 7
25 = 4 mod 7
26 = 1 mod 7

Difatti si può notare come non siano stati generati tutti i valori di b da 0 a 6.

Quindi i logaritmi discreti univoci in mod p di una base a esistono solo a è


una radice primitiva o generatore di p.

In questo modo sono maggiori le possibilità di nascondere il valore x (in quanto


esistono tutti i valori mod p). Difatti se a non fosse una radice primitiva, sarebbe
più facile scoprire il valore di x all'interno di un insieme chiaramente più piccolo,
riducendo di fatto il numero di possibili soluzioni e di conseguenza indebolendo l
la resistenza della funzione unidirezionale.

L'elevamento a potenza ha la proprietà di essere relativamente semplice da


calcolare, ma il logaritmo discreto è computazionalmente intrattabile quando si
tratta di partire dal risultato ed eseguire l'operazione inversa, complicato a tal
punto da renderlo una:
funzione One Way omputazionalmente intrattabile.

CALCOLO DEL LOGARITMO DISCRETO:

Sia a una radice primitiva o generatore in mod p:

In questo caso, (p – 1) è il più piccolo esponente positivo n che corrisponde a


(p – 1) per cui sia vera la seguente:

an ≡ 1 mod p => ap-1 ≡ 1 mod p

per il piccolo teorema di Fermat.


Ma siccome abbiamo che, se p è primo allora:

Φ (n) = (p – 1)

per il principio fondamentale di Eulero.


Di conseguenza vale che:

ax ≡ ay mod p => x ≡ y mod Φ (n)

e che quindi:

am1 ≡ am2 mod p <=> m1 ≡ m2 mod Φ (n) ≡ m2 mod (p – 1)

ATTACCHI ALL'ALGORITMO DISCRETO:

Non si conosce nessun algoritmo efficiente per il calcolo del logaritmo discreto loga b.

L'algoritmo più semplice che si può utilizzare, è quello di incrementare a per una
potenza k, fino a quando si arriva a trovare b. Questo algoritmo richiede un tempo di
esecuzione lineare di n e in tal modo esponenziale alla grandezza di n stessa.

Inoltre, quando p è piccolo è possibile calcolare il logaritmo mediante una ricerca


esaustiva, ma quando p è grande questo non è fattibile, alla stregua della
fattorizzazione.

1) BABY STEP – GIANT STEP:

E' un metodo di calcolo dei logaritmi discreti che si basa sull'analisi di


coincidenze tra 2 liste:

1) Lista baby calcolata con potenze piccole:

aj mod p

con j = {0, 1, …, N},


N scelto dall'utente basta il suo quadrato sia N 2 >= (p - 1)

2) Lista giant calcolata con potenze grandi:

(- N * k)
b*a mod p

con N = [2√(p - 1)] + 1,


e k = {0, 1, …, N}

Dopo aver costruito le liste, ad un certo punto si troveranno almeno due valori
uguali tra loro. Se si trova una coincidenza tra le due liste, si eguagliano le due
congruenze ed abbiamo che:

aj ≡ b * a(-N * k) ≡ a(j + N* k) ≡ b

e di conseguenza:

x=j+N*k
Il metodo funziona perché nelle liste devono esserci per forza di cose due valori
uguali, prima o poi. Non ne saranno mai sfornite.

La corrispondenza tra le due liste esiste perché:

0 <= x <= (p – 1) <= N2

si può scrivere in base N tramite la formula della divisione con quoziente e


resto, cioè dividendo x per N come:

x = x0 + x 1 * N

con:

0 <= x0, x1 < N

dove:

x / N = x1

con resto x0. E' chiaro che j sarà il resto:

x0 = j

e k il quoziente:

x1 = k

Per definizione, il resto j è espresso come:

j<N

allora è chiaro che j e k sono entrambi più piccoli di N.

Il numero di passi è proporzionale a:

N ≈ 2√(p

e richiede la memorizzazione di circa N numeri.

Questa tecnica vale solo per numeri primi grandi al massimo 10 20.
Si tratta di un attacco puramente deterministico: generando e confrontando
tutti gli elementi di ogni lista con gli elementi dell'altra ho un tempo di
esecuzione ed un impegno computazione veramente inaccettabile.
Per questo motivo si tende a generare solo la prima delle due liste (Baby Step)
in maniera ordinata, poi si genera un valore alla volta della seconda lista (Giant
Step): in questa maniera non ho bisogno di generare anche tutta la seconda
lista e se sono fortunato troverò la corrispondenza prima di generarla tutta.
2) INDEX CALCULUS:

Questo metodo è l'algoritmo noto più efficiente per il calcolo della x dei
logaritmi discreti in mod p. Esso fa uso di due procedure:

La prima procedura, fornisce un'insieme B (detta soglia) di numeri primi:

p1, p2, …, pB

relativamente piccoli (detta base di fattori), con la proprietà che una porzione
significativa degli elementi del gruppo mod p risultano avere quali fattori primi
soltanto elementi di B.

La seconda procedura, invece, fornisce un metodo efficiente per


fattorizzare gli elementi del gruppo mod p che risultino effettivamente
esprimibili a partire dai soli numeri primi presenti nella base B.

Il metodo dell'Index calculus prevede una fase di preprocessing, il cui scopo è


di calcolare il logaritmo discreto mod p di tutti i primi della base B.

FASE DI PREPROCESSING:

1) Procedura 1: Si scelga un base di fattori B = {p1, p2, …, pB}

2) Procedura 2: Si scelga in maniera casuale un xi appartenente al


gruppo mod (p – 1) escluso lo 0, finché non risulti che a^x i sia
fattorizzabile in termini dei primi in B:

a^xi ≡ ( p1^ a1i ) * … * ( pB^ aBi ) mod p

se e solo se:

xi ≡ aai * Dlog (p1) + … + aBi * Dlog (pB) (mod (p – 1))

3) Si ripeta il passo precedente B volte. Solitamente vengono calcolati


B + c valori di xi per aumentare la probabilità che il sistema di
congruenze lineari che ne deriva ammetta soluzione. Il valore della
costante c tipicamente è piccolo, ad esempio c = 10

4) Si risolva, nelle incognite Dlog p1 ,..., Dlog pB , il sistema ottenuto


combinando le congruenze lineari introdotte nei punti precedenti.

La fase di calcolo vera e propria del metodo dell'Index Calculus consiste di un


algoritmo probabilistico di tipo Las Vegas. Si tratta di una categoria di
algoritmi probabilistici che possono fornire due tipi di output:

1) La risposta corretta (con una certa probabilità t)


2) Nessuna risposta (con probabilità (1 – t))
L'algoritmo in esame tenta di ricondurre il calcolo di Dlog(b) ad
un'opportuna combinazione lineare dei logaritmi discreti dei fattori della
base, procedendo come segue:

CALCOLO DEL DLOG(b):

1) Si scelga in maniera casuale un s appartenente al gruppo mod (p – 1)


escluso lo 0

2) Si verifichi tramite la Procedura 2 vista nella fase di preprocessing, se

b * as mod p

è esprimibile per mezzo dei soli fattori della base B

3) Se cosi non è, l'algoritmo termina senza fornire alcuna risposta

4) Altrimenti, sia:

b * as ≡ ( p1^ c1 ) * … * ( pB^ cB ) (mod p)

Passando ai logaritmi discreti in ambo i membri, si ottiene:

Dlog(b) + s ≡ c1 * Dlog(p1 ) + … cB * Dlog(pB ) (mod p – 1)

=>

Dlog(b) ≡ c1 * Dlog(p1 ) + … cB * Dlog(pB ) - s (mod p – 1)

Quest'ultima espressione consente di ricavare il valore di Dlog(b), ovvero


l'esponente cercato, essendo note tutte le altre quantità presenti.

La probabilità che tale algoritmo Las Vegas fornisca una risposta


dipende dalla “qualità” della base dei fattori B. Tanto maggiore è la
porzione del gruppo mod p che risulta coperta da tale famiglia di numeri
primi, tanto più elevata sarà la probabilità che il valore s, scelto a caso al
punto 1 nel calcolo del Dlog(b) verifichi la condizione 2.

Inoltre, la scelta B = { i B numeri primi iniziali } presenta il vantaggio di


rendere semplice la determinazione della fattorizzazione degli elementi
x appartenenti al gruppo mod p in termini della base B (poiché trattandosi
di primi piccoli è possibile dividere x per i vari p i per stabilirne la
fattorizzazione), garantendo comunque una buona copertura del gruppo
mod p.
Comunicazioni sicure
1) BIT COMMITMENT:

La situazione è la seguente: due attori, Alice e Bob, comunicano tra loro ed uno
vuole dimostrare all'altro che possiede una certa informazione senza però
rivelarla. Per esempio, si pensi che Alice voglia vendere a Bob un algoritmo per
determinare l'esito corretto di una partita di pallone: Bob vorrà la garanzia, a
priori, che l'algoritmo funzioni perfettamente.

Questa tecnica si basa sull'utilizzo del logaritmo discreto.

1) Bob decide e stabilisce tutti i parametri del sistema:

αx (mod p) ≡ b

con a radice primitiva e p numero primo molto grande.

2) L'altro attore, Alice, sceglie allora un:

x <= (p – 2)

(non x <= (p - 1) perché se x fosse uguale a (p - 1) allora:

α(p - 1) = 1 mod p

per il piccolo teorema di Fermat) e fissa un bit specifico all'interno di x (magari il


secondo bit) come il bit che contiene l'informazione “nascosta” in questione:

se il bit è 0 vince la squadra A


se il bit è 1 vince la squadra B

ed è l'informazione che Bob vuole conoscere.

3) Alice calcola allora:

αx (mod p)

e ottiene b.

4) Alice allora spedisce b a Bob (che non è in grado di calcolarsi il logaritmo


discreto) che intanto guarda la partita ignorando l'informazione che Alice gli
ha mandato in anticipo; Bob in questa maniera possiede solo b e non a
oppure x in maniera disgiunta.

5) Dopo la partita Alice svela il valore di x (x non può essere cambiato a


posteriori da Alice perché altrimenti i conti con b precedentemente spedito non
tornerebbero. Questa è la garanzia che Alice non stia imbrogliando) e Bob
controlla il bit contenente l'informazione nel b che Alice aveva spedito prima: se
le sue informazioni coincidono Bob è convinto. Bob in questo modo trova b
nascosto all’interno di x e capisce se Alice aveva predetto giusto o meno.

Il sistema non può essere ingannato: b va risolto utilizzando la tecnica del


logaritmo discreto che è ancora un problema computazionalmente impossibile.

2) DIFFIE-HELLMAN KEY EXCHANGE:

Abbiamo sempre a che fare con i nostri due attori, Alice e Bob, che vogliono
scambiarsi una chiave su un canale sicuro.
Devono fare in modo che la chiave non sia leggibile e distinguibile.

1) Alice e Bob scelgono due numeri primi a e p sufficientemente grandi e li


rendono pubblici:

un attore, Alice, sceglie un numero segreto x <= (p - 2)


e l'altro attore, Bob, sceglie y <= (p - 2)

x ed y sono numeri random.

2) Alice allora calcola:

b1 = αx (mod p)

ed Bob calcola:

b2 = αy (mod p)

3) A questo punto, si scambiano le due informazioni b 1 e b2 sul canale sicuro

4) A questo punto Alice si calcola:

(αy)x (mod p) = (b2)x (mod p)

in base alle sue informazioni e Bob fa la stessa identica cosa con:

(αx)y (mod p) = (b1)y (mod p)

In questo modo entrambi ottengono lo stesso valore che sarà usato come
chiave pubblica che di fatto sul canale non è mai passata.

Anche se l’attaccante dovesse intercettare i due b 1 e b2 scambiati, per le


proprietà del logaritmo discreto non potrebbe farci nulla.

Questa fu l'idea che stava alla base dei primi crittogrammi della storia a chiave
pubblica.
3) ELGAMAL PUBLIC KEY CRYPTOSYSTEM:

Si tratta di un algoritmo crittografico molto sfruttato, tant'è che è usato anche


oggi poiché grandemente sicuro.

Si basa sul concetto di chiave pubblica e privata, in quanto viene usata la chiave
pubblica del destinatario per cifrare, mentre la decifratura viene eseguita con la
chiave privata del destinatario.

I nostri due attori, Alice e Bob, comunicano. Supponiamo che Alice voglia
spedire un messaggio a Bob.

1) Alice ha un messaggio m da cifrare e per farlo ha bisogno delle informazioni


del sistema generate da Bob, ovvero:

p numero primo grande


a radice primitiva, con a < (p - 1)
s random che è la chiave segreta di Bob

2) Bob allora calcola:

b ≡ as (mod p)

ed espone la chiave pubblica formata da:

PUB (a, p, b)

L'informazione s continua così a rimanere segreta.

3) Alice allora scarica la chiave pubblica dal server dove l'ha pubblicata Bob e
cripta il suo messaggio m:

genera un numero k random e segreto, k < (p – 1) e calcola:

r ≡ αk (mod p)

t ≡ bk * m (mod p)

4) Alice prende allora la coppia (r, t) e la spedisce a Bob dicendo che coincide
con il messaggio m cifrato. Il crittotesto è infatti formato da due informazioni e
non più da una sola: il messaggio non è stato manipolato, bensì nascosto.

5) Bob riceve la coppia e calcola:

–s
t*r ≡ m (mod p)

per poter leggere il messaggio.


Ma come è possibile?

DIMOSTRAZIONE:

Verifico che:

–s
m=t*r mod p

Sia:

t = bk * m mod p

r = ak mod p

b = as mod p

Allora:

((bk * m) * (ak))–s mod p =

= ((as)k * m) * (ak) -s
mod p =

= a(k * s) * m * a( - k * s) mod p = m

Ad ogni aspirante attaccante mancano k ed s; sul canale passano solo le


informazioni del logaritmo discreto che non può essere invertito.
Tuttavia ci sono dei limiti da rispettare: ogni volta che cambia m non si
possono usare gli stessi k, perchè se tengo fisso k l'attaccante potrebbe
dedurre che:

t1 = m1 => t1 = bk * m1 mod p

t1 = m2 => t2 = bk * m2 mod p

con k sempre uguale nel tempo. Ma si sa che:

t1 / m1 = bk

t2 / m2 = bk

e che basta invertire l'equazione per trovare:

m2 = (m1 / t1) * t2

Spedire sia r che t sembra dispendioso dal punto di vista che si mandano
troppe informazioni sul canale, tuttavia rende l'intero sistema sicuro.
Funzioni Hash
Le funzioni hash vengono utilizzate per firmare documenti e per verificare l’integrità
dei dati, cioè sapere se quello che è stato trasmesso è stato anche ricevuto
correttamente. E’ molto più conveniente firmare l’hash che il documento intero.

Le funzioni hash prendono in input un messaggio m di lunghezza arbitraria e


restituisce un output h di lunghezza fissata.
Si possono chiamare anche message digest e si esprimono come:

h = H(m)

con h risultato della funzione H applicata al messaggio m.

Il dominio di questo genere di funzioni contiene i messaggio in chiaro e la sua


dimensione è infinita, tuttavia il suo codominio contiene un numero massimo di
equivalenti cifrati dei messaggi del dominio. Questo vuol dire che una funzione hash è
capace di mappare due o più messaggi in chiaro differenti nello stesso hash.

Una funzione hash H prende in input un messaggio m qualsiasi ma l'hash h prodotto in


output è sempre della stessa medesima dimensione, a prescindere da quella del
messaggio in chiaro.

Proprietà:

1) PREIMAGE RESISTANT:

In una funzione hash h = H(m) dev'essere computazionalmente intrattabile


riuscire a trovare m (dev'essere quindi una funzione one way) a partire da h.

2) SECOND PREIMAGE RESISTANT:

Si pretende che dati due testi in chiaro m 1 ed m2 non sia possibile che in un
tempo ragionevole si possa trovare due valori che collassano sullo stesso
identico hash nell'insieme del dominio della funzione.

1) HASH BIT – BY – BIT:

Questo tipo di funzione hash costituisce un esempio di come tali funzioni


possono essere implementate, anche se non costituisce una funzione hash
reale.

Si prende m e lo si divide in n blocchi:

m = b1, b2, b3 ……., bn


,
ognuno dei quali a loro volta divisi da una sotto quantità di altri r blocchetti:
b1 = b1,1, b1,2, …, b1,r

b2 = b2,1, b2,2, …, b2,r

...

bn = bn,1, bn,2, …, bn,r

Come calcolo l'hash bit a bit? Ogni blocco dell'hash viene calcolato come lo XOR
tra tutti i bit al primo posto in ogni blocco in cui è suddiviso il messaggio in
chiaro:

h1 = b1,1 XOR b2,1 XOR … XOR bn,1

h2 = b1,2 XOR b2,2 XOR … XOR bn,2

E così via fino al calcolo di hr

.…

hr = b1,r XOR b2,r XOR … XOR bn,r

In questo modo, l'hash dato sarà:

H = h1, h2, …, hr

Questo modello di funzione hash mescola i bit dei blocchi in cui è stato
suddiviso il messaggio in chiaro. Se per caso si commette un errore su un bit di
conseguenza risulta sbagliato anche il relativo blocco di hash.

Nella realtà le funzioni hash vengono usate:

1) Garanzia di autenticità:

Si prende il messaggio in chiaro m e la sua funzione hash e li si spedisce


accodati nel canale di rete. Tuttavia prima di mandare il pacchetto in
internet cripto tutto con la mia chiave condivisa.

Chi riceve il pacchetto dall'altra parte estrae il messaggio e la hash ed ad


m applica ancora la funzione hash, confrontando così l'hash ottenuta con
quella ricevuta nel pacchetto: se le due coincidono vuol dire che il
pacchetto ed il messaggio non sono stati corrotti.

Così è garantita l'autenticità di m. Però il messaggio è infatti a rischio di


lettura. Un ipotetico attaccante, se in possesso della chiave di cifratura,
potrebbe prendere il pacchetto, aprirlo, eliminare il messaggio e
sostituirlo con uno nuovo; la protezione tra chi spedisce e riceve il
messaggio non è garantita.
Il problema può essere risolto con l'utilizzo di una firma digitale:

si prende m e si calcola la sua hash poi si “firma” con la chiave privata


solo ed esclusivamente per certificare l'autenticità di chi è stato a spedire
il pacchetto.

Si firma il messaggio ma anche l'hash, peccato che il messaggio potrebbe


avere lunghezza infinita: se il messaggio risulta essere troppo lungo da
firmare si firmerà solo l'hash.

La confidenzialità è compromessa poiché il messaggio, nel peggiore delle


ipotesi, viene spedito completamente in chiaro.

2) Garanzia di confidenzialità:

Devi criptare il mio pacchetto in partenza con la mia chiave privata: in


questo modo il pacchetto comprende il messaggio e l'hash già criptata
del messaggio stesso.

2) SECURE HASH ALGORITHM (SHA – 1):

Si tratta di un tipo di funzione hash molto sfruttato nei certificati digitali. E’


l’algoritmo che fa uso di funzioni hash raccomandato dal NIST.

In input si ha un vettore di grandezza variabile (messaggi m) e in output un


messaggio di 32 * 5 = 160 bit.

L'input viene elaborato a blocchi di 512 bit e se il messaggio non è congruo


(ovvero non è multiplo di 512) è lecito aggiungere del padding finale per “far
tornare i conti”. Per prima cosa è necessario accodare i bit di padding ed, a
seguire, si espande il tutto, quindi si inizializza e si elabora il messaggio.

IL PADDING:

Si forma mettendo un 1 alla fine del messaggio originale e poi una lista di
zeri fino a 64bit dalla fine.

Gli ultimi 64bit (detti espansione) contengono la rappresentazione della


lunghezza del messaggio in mod 269.

Quindi, se si inizia con un messaggio m di lunghezza non congrua a 512


bit, si fa padding finché l'intero messaggio con la sua ulteriore espansione
dovrà infatti essere congruo a 0 mod 512.

Una volta ottenuto il messaggio congruo a 0 mod 512 con o senza padding e
con la sua ulteriore espansione, il messaggio andrà ora in pasto alla funzione
hash di SHA-1.
La funzione hash di SHA-1 lavora su 80 round, ma non utilizza gli stessi dati per
tutti quanti, infatti, ogni 20 round cambia funzione e costanti che utilizza (infatti
utilizza 4 funzioni ft() prestabilite più quattro costanti kt).

FUNZIONAMENTO:

1) Inizializzo i registri H0, H1, H2,H3, H4 con delle costanti prestabilite dai
creatori di SHA-1

2) Il messaggio m, se non lo è già, viene fatto diventare un multiplo di


512 facendo il padding finché non è congruo a 0 mod 512

3) Il messaggio m viene diviso in blocchi da 512bit

4) Si incomincia dal primo blocco m 1 viene diviso in 16 sottoblocchi da


32bit (w0, ..., w15)

5) Tutti gli altri blocchi fino a w79 (in quanto servono 80 sottoblocchi,
ovvero da w0 a w79) vengono calcolati nel seguente modo:

wt = (wt-3 XOR wt-8 XOR wt-14 XOR wt-16) << 1

dove wt va shiftato a sinistra di un bit. In questa maniera si


calcolano tutti i 79 valori di SHA.

6) Inizializzo i cinque registri (A, B, C, D, E) che mi servono per la


computazione con i valori definiti nel passo 1, ovvero:

A = H0 B = H1 C = H2 D = H3 E = H4

7) Vengono eseguite le seguenti operazioni su di essi

7.1) Il registro A va in B del round successivo

7.2) B viene shiftato di 30 bit a sinistra e va in C del round


successivo

7.3) Il registro C va in D del round successivo

7.4) La funzione del round ft() (varia ogni 20 round), prende in


ingresso B, C, D prima che venga fatto loro qualunque operazione

7.5) Il registro D va in E del round successivo

7.6) Il registro E viene XORato con ft(), registro A << 5 (ovvero


shiftato a sinistra di 5 biti), w t di turno e kt di turno ed il tutto viene
mandato in A del round successivo

7.7) Ai registri H0, H1, H2, H3, H4 vengono sommati rispettivamente i


nuovi valori di A, B, C, D, E
8) Le operazioni del punto 7 vengono eseguite per 80 round variando ogni 20
round le operazioni di ft() e la costante kt.

9) L'output finale della funzione hash di SHA-1 è costituito da questi 5 registri


H0, H1, H2, H3, H4:

H0 || H1 || H2 || H3 || H4

che accodati danno i bit fissati (32 * 5 = 160 bit).

SHA1 è già stato attaccato più volte ma è difficile riuscire a trovare


delle collisioni nel suo dominio.

ATTACCHI ALLE FUNZIONI HASH:

1) ATTACCO DEL COMPLEANNO:

E’ una tecnica che può essere usata per attaccare le funzioni hash in
maniera probabilistica, in quanto si basa sulla probabilità di trovare due
messaggi diversi con lo stesso hash.
Il paradosso del compleanno può essere spiegato con un esempio:

Si pensi a quale possa essere la probabilità che due persone facenti


parte di uno stesso gruppo compiano gli anni lo stesso giorno? Tale
probabilità è:

1 – (1 / 365)

E se le persone che compiono gli anni lo stesso giorno fossero tre


sarebbe:

[ 1 – (1 / 365)] * [1 – (2 / 365)]

E se le persone in questione fossero 23? Si andrebbe avanti a moltiplicare


fino ad arrivare a:

1 – (22 / 365)

Facendo tutti i conti si ottiene 50,7% che è una probabilità molto alta!
Questo risultato è dato dal fatto che le considerazioni fatte prima sono
vere, ma solo in parte, infatti, il nostro problema non era trovare che due
persone in particolare compissero gli anni lo stesso giorno, andava bene
una qualunque coppia del gruppo. Questo fatto porta a confrontare tutte
le possibili coppie che si possono formare con 23 persone e questo porta
ad un aumento della percentuale di successo. Con 30 persone la
probabilità sale ancora a 70% circa e con 40 persone si raggiunge l'89%
circa.

La probabilità cresce con l'aumentare delle persone conteggiate. La


formula più generale del problema può essere riassunta così:

la probabilità che due persone facenti parte dell'insieme r facciano una


stessa scelta in un insieme dato di possibilità N e pari a:

1 – e^[ - (r2) / (2 * N)]

Ipotizzo che:

[(r2) / (2 * N)] = log(2)

Allora ottengo che:

1 – e^[ - log(2)] =

= 1 – [1 / (e^log(2)) = 1 – (1 /2) = 50%

In pratica, scegliendo un r per cui:

[(r2) / (2 * N)] = log(2)

ho la certezza che la probabilità che ci sia una corrispondenza è del 50%.


Infatti:

[(r2) / (2 * N)] = log(2) =>

=> r2 = log(2) * (2 * N) =>

=> r = 2√(2 * log(2) * N)

e sorvolando sui conti r = 1,177. Quindi per farlo funzionare bene:

2
r= √N

Se voglio far crescere la probabilità mi basta far crescere r.


Usiamo allora queste probabilità per attaccare le funzioni hash:
sfruttiamo le collisioni per trovare 2 documenti che producano lo stesso
hash e che quindi possano essere interscambiabili.
Data una funzione hash cerco 2 elementi del suo dominio che tramite la
funzione finiscano entrambi nello stesso elemento del codominio.

N è il numero degli elementi nel codominio


r è un sottoinsieme del dominio, ma di r ne prendo tanti quanti bastano
per prendere in considerazione TUTTI gli elementi del codominio.

Creo allora due liste ed ogni lista è formata da r elementi.

Calcolo l'hash di ogni elemento di ogni lista e cerco corrispondenze tra le


due liste.
Sono stato molto o tanto fortunato a seconda di quanto grande ho scelto
r: lo conferma il paradosso del compleanno.

Perché funzioni bene r dev'essere simile alla radice quadrata di N, come è


stato dimostrato prima. Il tempo che si dovrebbe impiegare a fare questo
tipo di conto è ragionevole anche sulle macchine domestiche.

Questo è l'attacco di base per forzare le funzioni hash.


L'attacco del compleanno funziona anche con l'algoritmo del logaritmo
discreto: in questa maniera effettuo però un attacco probabilistico e non
più deterministico come con il metodo tradizionale.

COME GESTISCO LE MULTI-COLLISIONI?

Voglio cercare più collisioni tra più elementi e modifico la formula come
segue:

r = k√N^(k - 1)

se voglio trovare esattamente k collisioni. Dopotutto mi basta intervenire


sul rapporto tra r e N.

Fino al 2004 si pensava che la cardinalità del codominio fosse troppo


piccola. Si pensava allora di concatenare diverse hash tra loro per
allungarne il codominio ma si è dimostrato invece che esiste un attacco
efficace anche in questo frangente.

2) MODELLO DELL'ORACOLO CASUALE:

Prendo una funzione hash e le do due input diversi in due momenti


diversi. In questa maniera è ovvio che genero due output diversi.

L'hash è forte quando, in questa situazione, non so aspettarmi un certo


hash dato un certo input.

Ognuno può dare un input e l’algoritmo restituisce il corrispondente hash,


calcola la probabilità che input diversi abbiano lo stesso hash.
Se una funzione hash funziona come un oracolo casuale, allora l'hash
è forte. Se invece si riconoscono gli output a partire dagli input l'algoritmo
è debole e si è in grado di attaccare il sistema con un attacco
distinguisher.

FUNZIONI HASH PER CIFRARE:

Le funzioni hash accettano input di lunghezza arbitraria e restituiscono output di


lunghezza fissata. Le funzioni hash possono essere usate per cifrare un
messaggio e non solo per hasharlo.

Alice e Bob che vogliono comunicare utilizzano la chiave condivisa K ab

1) Alice prende un testo in chiaro e lo divide in blocchi p 1, p2, …, pn

2) Alice Calcola allora l'hash della della chiave condivisa:

H(Kab)

e prende gli 8 bit meno significativi dell'hash della chiave condivisa, quindi
calcola:

x1 = L8 (H(Kab))

3) Alice cifra il primo blocco del testo in chiaro p 1 facendo lo XOR con x1:

c1 = p1 XOR x1

4) Alice questo punto si calcola x2 per il secondo blocco:

x2 = L8 (H(Kab) || x1)

e cifra il secondo blocco del testo in chiaro p 2 facendo lo XOR con x2:

c2 = p2 XOR x2

e cosi via per tutti gli altri blocchi p3, …, pn.

5) Bob per decifrare farà l'operazione inversa, ovvero:

p1 = c1 XOR x1
p2 = c2 XOR x2

pn = cn XOR xn

Se Alice volesse usare una sua password giornaliera per cifrare potrebbe
appenderla come è stato fatto per x1, però deve ricordarsi di spedirla a Bob.

Se l’attaccante intercetta la password giornaliera non può farci niente perché


non conoscendo la chiave condivisa kab non riesce a risalire al messaggio.
Firma digitale
Spesso si ha a che fare con documenti elettronici che non sono distinguibili da loro
eventuali copie. La firma digitale vuole occuparsi della risoluzione intelligente di tale
problema.

1) RSA SIGNATURE:

Questa è la prima tecnica per firmare con RSA.


Per effettuare una firma digitale servendosi di RSA occorrono tutti i parametri
prestabilisti da RSA., di conseguenza PUB(e, n) e PRIV(p, q, d).

1) Alice svolge tutte le operazioni fatte in RSA e rende pubbliche PUB(e, n),
tiene private PRIV(p, q ,d)

In più firma il messaggio facendo:

f = md mod n

e spedisce a Bob (firma, m)

Si eleva il messaggio al valore di d perché d appartiene alla chiave privata


PRIV(p, q, d) mentre e appartiene a quella pubblica PUB(e, n) e di conseguenza
lo può generare solo il firmatario. In questo modo si genera la firma dove m è il
documento digitale firmato.

2) Bob si calcola:

x ≡ f e mod n

Se x = m allora Bob accetta la firma di Alice.

2) BLINDED SIGNATURE:

Questa è la seconda tecnica per firmare con RSA.


Permette rispetto la prima tecnica di Firmare un documento di cui non si
conosce il contenuto.

Per effettuare una firma digitale servendosi di RSA occorrono tutti i parametri
prestabilisti da RSA., di conseguenza PUB(e, n) e PRIV(p, q, d).

1) Alice svolge tutte le operazioni fatte in RSA e rende pubbliche PUB(e, n),
tiene private PRIV(p, q ,d)

2) Bob sceglie k tale che:

GCD(k, n) = 1
calcola:

t = ke * m mod n

e spedisce t ad Alice (m è il messaggio nascosto).

3) Alice firma t facendo:


d
s≡t mod n

e spedisce s a Bob.

4) Bob calcola:

s / ke ≡ md

e verifica la firma di Alice.

In tutto questo Alice non ha mai visto il messaggio m, ma l’ha firmato, in questo
modo Bob potrebbe truffarla se solo lo volesse.

3) ELGAMAL SIGNATURE SCHEME:

In questo algoritmo la firma viene appesa.

Per effettuare una firma digitale servendosi di Elgamal occorrono tutti parametri
prestabilisti da Elgamal., di conseguenza PRIV(l) e PUB(a, b, p).

Operazioni di firma:

1) Alice svolge tutte le operazioni fatte da Elgamal e rende pubbliche


PUB(a, b, p), tiene private PRIV(l)

2) Alice sceglie k tale che:

GCD(k, (p - 1)) = 1

e determina un r tale per cui:

r ≡ ak mod p

Poiché non si commette alcuna cifratura, non è necessario calcolare anche t,


quindi Alice si limita a calcolare:
-1
s≡k * (m - l * r) mod (p – 1)

A questo punto, Alice spedisce a Bob il messaggio firmato, ovvero (m, r, s),
ovvero il messaggio in chiaro più r ed s sul canale

3) A questo punto, Bob per verifica che s sia autentico scarica dal server la
chiave pubblica PUB(a, b, p) e calcola:
v1 ≡ b r * r s mod p

assieme ad:
m
v2 ≡ a mod p

La firma è valida se:

v1 = v2

DIMOSTRAZIONE:

m
v2 ≡ a mod p

ma voglio riscrivere:

m=s*k+l*r

allora:

v2 ≡ a^(s * k + l * r) mod p

ma posso riscrivere tutto come:

v2 ≡ (a l ) r * (a k) s mod p

sapendo che:

a l= b

a k= r

quindi:

v2 ≡ r s * b r mod p

che è uguale a v1.

Il problema sorge quando, cifrando più e più volte, si può risalire a parte del
messaggio se continuo ad utilizzare sempre lo stesso k.

4) HASHING AND SIGNING:

Questi due metodi appena spiegati (la firma con RSA e quella di ElGamal)
appartengono ad utilizzi della firma digitale molto diversi tra loro:
1) Con RSA manderò sul canale solo la firma senza il messaggio annesso, in
modo da risalire al testo in chiaro tramite un algoritmo di cifratura

2) In Elgamal appendo in coda al messaggio la sua relativa firma

Tuttavia l'utilizzo del metodo di RSA è discutibile.


Il documento che si vuole cifrare potrebbe essere molto lungo ed altrettanto
potrebbe rivelarsi il processo di firma.

In questo caso sono costretto a firmare solamente l'hash del messaggio.

Calcolo infatti l'hash di m e poi cifro l'hash con RSA ed invio il messaggio
assieme a questa firma.

Questo modo di operare porta dei vantaggi considerevoli, infatti, in questo


modo l’operazione di firma è molto veloce in quanto vengono firmati una
quantità limitata di dati.

Il nuovo problema che si viene a creare è il seguente:

come garantire l'unicità di quell'hash quando chiaramente gli hash possono non
essere unici per documenti differenti?

Si utilizza allora un algoritmo hash forte che, assicura di non trovare nessuna
collisione in tempo utile.

L'attaccante allora vorrebbe trovare un documento fasullo che possieda lo


stesso hash, ma in questa maniera diventa quasi impossibile trovarne uno di
senso compiuto che una volta ricevuto non desti sospetti.

Per escludere il presentarsi di questo problema basta cambiare un dettaglio


all'interno del testo per cambiare radicalmente l'hash che ne verrà prodotto.
In questo modo, il possibile attaccante non ha abbastanza tempo per generare
tutti gli hash.

5) DSA (DIGITAL SIGNATURE ALGORITHM):

È stato proposto dal NIST nel 1994 e si tratta di un algoritmo considerato sicuro
ed uguale al 90% a quello concepito da ElGamal. Il NIST puntava sulla sicurezza
facendo uso di specifici parametri.

E’ una schema di cifratura dove la firma viene appesa, lavora su input arbitrario
e l’output è di 160bit.

Si procede come segue:


1) Alice sceglie p e q numeri primi e sufficientemente grandi con q di 160
bit e p di almeno 512 bit tale per cui:

(p - 1) dev'essere divisibile per q, ovvero q / (p – 1) ≡ 0

2) Alice genera allora una radice primitiva g (in mod p) e calcola:

(p – 1) / q
a≡g (mod p)

e:

a q ≡ 1 (mod p)

3) Alice sceglie un l segreto tale che:

0 < l < (q – 1)

e calcola:

b ≡ a l (mod p)

4) A questo punto Alice avrà come chiave pubblica:

PUB(a, b , p, q)

e come chiave privata:

PRIV(l)

ed inizia qui la funzione di firma del messaggio m

5) Alice sceglie un k casuale e calcola:

r = (a k (mod p)) (mod q)

mentre s sarà dato da:

-1
s≡k (m + l * r) (mod q)

6) Alice spedisce sul canale la firma, che sarà data da f(m, r, s) ovvero il
messaggio in chiaro più r ed s sul canale

7) Bob a questo punto scarica dal server la chiave pubblica di Alice, ovvero:

PUB(a, b , p, q)

e si calcola:
-1
u1 ≡ s * m (mod q)
-1
u2 ≡ s * r (mod q)
u1 u2
v = (a *b (mod p)) (mod q)

8) La firma risulta accettabile se:

v=r

DIMOSTRAZIONE:

Ricalcolo m nella seguente forma ricavandolo da s:

m ≡ (k * s – a * r) (mod q)

poi moltiplico entrambi i termini per s -1:


-1 -1
m*s ≡ (k * s – a * r) * s (mod q)

questo implica che:


-1
m*s ≡ (k – a * r * s -1) (mod q)

allora:
-1
k≡s * m + a * r * s-1 (mod q)

ma noi sappiamo che:

r = (a k (mod p)) (mod q)

quindi sostituendo in r la k otteniamo:


-1
r = (a^(s * m + a * r * s-1) (mod p)) (mod q)

adesso noi sappiamo che:


-1
u1 ≡ s * m (mod q)
-1
u2 ≡ s * r (mod q)

quindi sostituendo gli esponenti di a otteniamo:


u1 + ( l u2)
r = (a * mod p) (mod q)

e quindi poiché sappiamo che:

b ≡ a l (mod p)

riscriviamo r tramite b:
u1 u2
r = (a *b (mod p)) (mod q)

e tutto questo risulta essere uguale a v e che quindi r = v.


Autenticazione
Attraverso un uso proprio dell'autenticazione si vuole tutelare la veridicità delle
chiavi pubbliche: dopotutto, chi ci assicura che quella che abbiamo tra le mani sia
davvero la chiave del nostro interlocutore e non quella di colui che vuole attaccare il
nostro sistema?

1) MAN IN THE MIDDLE:

Questo è una tipologia di attacco all’algoritmo di Diffie-Helman e consiste, da


parte dell’attaccante, di mettersi in mezzo tra il mittente e il destinatario
spacciandosi una volta per l’uno e una volta per l’altro riuscendo così a
leggere/modificare i messaggi a proprio piacimento senza che i due interlocutori
sospettino niente.

FUNZIONAMENTO:

1) Alice e Bob vogliono comunicare, sanno che il canale è insicuro e quindi


usano la strategia di Diffie-Helman per scambiarsi la chiave

2) I due scelgono a, p in comune poi:

Alice calcola b1 ≡ ax (mod p)

Bob calcola b2 ≡ ay (mod p)

e si spediscono b1 , b2.

3) Eva che sta nel mezzo intercetta b1 , b2 , si calcola:

b3 ≡ az (mod p)

e lo spedisce ad Alice e Bob

4) Alice e Bob pensano di aver ricevuto il b l’uno dell’altro e non sospettano


minimamente che invece si tratta di quello di Eva

5) Ogni volta che Alice manda un messaggio, Eva lo intercetta, lo decifra, e poi
lo cifra nuovamente usando la chiave che Bob è in grado di decifrare e poi gli
spedisce il messaggio

DIFESA:

Basta modificare il protocollo per arginare la situazione: gli interlocutori devono


spedirsi sul canale ax e ay firmando ogni volta il messaggio:

Alice αx ed anche la firma: Ek(firmaAlice(b1 ,b2)


Bob αy ed anche la firma: Ek(firmaBob(b1 ,b2)
1) Alice genera:

b1 ≡ αx (mod p)

e lo spedisce a Bob

2) Bob calcola la chiave segreta e condivisa con Alice:

k ≡ (b1)y (mod n)

3) Bob genera:

b2 ≡ αy (mod n)

e la propria firma:

Ek(firmaBob(b1, b2))

e li spedisce ad Alice

4) Alice si calcola la chiave segreta e condivisa con Bob:

k ≡ (b2)x (mod n)

e decifra:

Ek(firmaBob(b1 ,b2))

e ottiene la firma di Bob

5) Alice chiede all’Autentification Autority di controllare la firma di Bob

6) Se la firma di Bob è verificata, Alice genera la propria firma:

Ek(firmaAlice(b1, b2 ))

e la spedisce a Bob

7) Bob decifra e chiede all’Autentification Autority di controllare la firma di Alice

8) Se la firma di Alice è verificata, i due sono sicuri di comunicare correttamente

L’Autentification Autority ovvero l'ente che verifica la firma è esterno ed autentico


tanto che l'attaccante non può sperare di simularlo.
2) DISTRIBUZIONI DELLE CHIAVI:

Quando si ha a che fare con tanti utenti si hanno anche tante chiavi e per
scambiare queste chiavi si utilizzano in genere due tipi di protocolli:

1) KEY DISTRIBUTION:

Questi protocolli prevedono che un utente generi e distribuisca le chiavi


(RSA)

2) KEY AGREEMENT:

In questi protocolli è la chiave che viene generata da una coppia di


interlocutori e spezzata in più parti (Diffie - Helman).

Entrambi questi protocolli generano problemi che si possono risolvere con


l'utilizzo del protocollo di Blom, molto semplice e molto sfruttato.

1) BLOM KEY PRE-DISTRIBUTION SCHEME:

Abbiamo n utenti e un numero p primo con p > n,


ogni utente = u, conosce p.

1) Viene assegnato un numero distintivo per ogni utente:

ru(mod p)

2) L’autority (Trent) sceglie tre numeri random:

a, b, c (mod p)

3) Per ogni utente u calcola:

au = a + b * ru

bu = b + c * r u

4) Ogni utente forma:

g * u = a u* bu * x

5) Se Alice(A) vuole comunicare con Bob(B) calcola:

kAB = gA * (rB)

mentre Bob calcola:

kBA = gB * (rA)

Entrambi ora hanno una chiave in comune.


Tuttavia anche questo protocollo è vulnerabile ed è attaccabile tramite
una coalizione di k utenti. Ovviamente, k è una soglia sotto la quale
l'attacco è inefficace, tuttavia settare k troppo alti rallenta ed
appesantisce l'algoritmo.

Ci si può avvalere, allora, di enti fidati per la tutela della veridicità delle
chiavi generate e sono loro che, per primi, generano e gestiscono queste
chiavi all'interno del loro database.

2) KERBEROS:

Si pensi che il client voglia avere un servizio dal server ma che non glielo
voglia chiedere direttamente.

Prima si autentica presso l'ente fidato e costui restituisce al client una


specie di bigliettino. Il client allora passa attraverso una “biglietteria”
dove, dichiarandosi con le informazioni ricevute dall'ente fidato riceve un
nuovo biglietto. Di conseguenza richiede che il client si autentifichi prima
di poter accedere ai servizi del server.

Solo ora il client si rivolge al server per ottenere il servizio richiesto.

client, server, Autentification Autority (Trent), grating server (GS).

Si procede come segue:

1) Il Client chiede all'Autentification Autority un ticket

2) Se l'Autentification Autority si fida del client, gli spedisce un


ticket criptato con la chiave segreta del client

3) Prima di poter richiedere servizi al server, il client deve chiedere


permesso al Grating Server (GS) spedendogli il suo ticket

4) Il Grating Server (GS) controlla il ticket e se tutto è ok, restituisce


al client un nuovo ticket di grant

5) A questo punto il client spedisce al server il nuovo ticket di grant


e le sue credenziali al server

6) Il server controlla e se tutto è ok, inizia a fornire i servizi al client

3) PKI (PUBLIC KEY INSTRUCTION):

Le chiavi di cui disponiamo le fornisce l'autorità per le certificazioni che le


firma appena prima di immetterle nel suo database.

Ma come fidarsi delle Certification Authority?


Lo si fa grazie al PKI, che costituisce una gerarchia di fiducie simile ad una
infrastruttura.

A loro volta le Certification Authority non solo generano chiavi e


garantiscono per le altre autorità ma delegano il compito alle Registration
Authority di certificare altri utenti al posto loro.

Quindi:

1) CA o Certification Authority firmano le chiavi e può delegare alle RA

2) RA o Registration Authority hanno la possibilità di firmare i


certificati delle CA

Si sfrutta così uno schema gerarchico.

4) PGP:

Sfrutta una web of thrust: gli utenti definiscono 4 livelli di fiducia da


affidare ad altri utenti relativamente alla sicurezza delle loro chiavi.

In questa maniera non si passa per la Certification Authority.

5) SET, SSL, TLS:

1) SET:

E' un protocollo di Visa e Mastercard per la tutela delle transazioni.

2) SSL:

Arriva da Netscape e si è fermato alla versione 3 perché si è


rivelato uno standard internazionale. Dalla versione 3.1 ha
cambiato nome in TLS.

3) TLS:

E' l'evoluzione di SSL da quando è diventato standard.

SSL e TLS sono utilizzati più comunemente. Sono protocolli che assicurano la
generazione di un canale sicuro con un uso massivo di algoritmi di crittografia.
Protocolli di sicurezza
I protocolli di sicurezza fanno un uso massivo di crittografia per proteggere gli attori di
una conversazione e le informazioni che si scambiano tra loro.

Tuttavia, su internet, esistono banche di fama mondiale che utilizzano gli stessi identici
protocolli di sicurezza della posta elettronica di ateneo.

1) PROTOCOLLI DI ZERO – KNOWLEDGE TECHNIQUES

Si tratta di tecniche che permettono di dimostrare la conoscenza da parte di un


attore di una certa informazione senza dover per forza rivelare tale informazione
all'altro attore della conversazione. Si parla di tecniche probabilistiche.

Alice vuole dimostrare a Bob di conoscere una terminata informazione, ma non


vuole dirla direttamente a Bob, d’altra parte quest’ultimo vuole una prova di
ciò che Alice va affermando.

FUNZIONAMENTO:

Sia n = p * q, il prodotto di due numeri primi grandi.


Sia y un quadrato mod n con MCD(y, n) = 1

Ricordiamoci che trovare una radice quadrata mod n è un problema difficile,


equivalente a fattorizzare n.

Tuttavia Alice afferma di conoscere una radice di y. Bob vuole verificare tale
affermazione, ma Alice non vuole rilevare s. Procedono nel seguente modo:

1) Alice sceglie casualmente r1 ed calcola r2 come:

r1 -1 * s mod n

cosi che vale:

r1 * r2 = s mod n

Supporremo che MCD(r1 , n) = 1, se no Bob ottiene facilmente un fattore di n.

2) Per dimostrare di possedere s, Alice calcola:

x1 ≡ r12 mod n

x2 ≡ r22 mod n

e li spedisce entrambi a Bob.

3) Bob controlla che:


x1 * x1 ≡ y mod n

quindi sceglie una delle due x e chiede a Alice di calcolargli la radice quadrata
del suddetto numero

4) Se Alice ha spedito le x corrette calcolate come sopra non ha problemi ad


esaudire la richiesta di Bob, altrimenti se non è in grado vuol dire che in realtà
non conosceva l’informazione di cui andava dicendo

5) L’operazione viene eseguita più volte con diverse x fino a quando Bob non è
soddisfatto

2) DIGITAL CASH:

Okamoto e Ohta definirono le proprietà che il denaro digitale dovrebbe avere:

1) L’acquirente deve poter rimanere anonimo


2) Non deve essere copiato e duplicato/riusato
3) Garantire transazioni sicure sulla rete
4) La transazione deve poter venire anche offline
5) Il denaro deve poter essere trasferibile
6) Il denaro deve essere divisibile in tagli più piccoli

Sono coinvolti tre attori: La banca, il mercante, e lo spender.


La banca ha un identificativo univoco, e lo spender e il mercante devono
registrarsi presso di essa.

Le fasi di una corretta transazione di denaro digitale sono quattro ed alla fine
della transazione è necessario fare un controllo anti frode: magari uno o più
agenti della transazione sono fraudolenti. Le fasi della transazione sono:

1) Inizializzazione
2) Generazione del denaro e scambio di denaro:

Lo spender chiede alla banca di creare moneta, la banca identifica lo


spender, crea il denaro e lo mette a disposizione dello spender che a sua
volta lo trasferisce al mercante. In fine il mercante lo depositerà in banca
sul suo conto.

3) Incasso del denaro:

Il mercante controlla i soldi ricevuti in particolare che non siano stati spesi
due volte e poi accetta/rifiuta il pagamento.

4) Controllo anti frode:

La banca controlla tutti i tipi di frode tentabili dal mercante e dallo


spender.
Schemi di condivisione del segreto
Può capitare che si abbia un “segreto” da nascondere ma che non ci si fidi
nell'affidarlo ad una sola persona. È opportuno allora suddividere questo segreto tra
un gruppo di persone che dovranno poi collaborare e riunirsi per poter ottenere il
segreto intero.

1) SCHEMI DI CONDIVISIONE DEL SEGRETO:

Trattano di schemi matematici relativi alle “chiavi” condivise da questo gruppo


di persone in comunicazione.

Il segreto non è altro che suddiviso in piccole sotto parti, ogni pezzo non è
uguale ad un altro e si distribuisce un pezzo di chiave ad ogni persona in modo
tale che una singola persona non sia in grado di ricostruire la chiave.

Il caso più semplice si verifica quando vogliamo dividere un messaggio M


rappresentato da un numero intero tra due persone, Alice e Bob, in modo che
nessuno dei due possa ricostruire il messaggio da solo:

1) Ad Alice assegniamo un numero casuale r

2) A Bob assegniamo invece (M – r)

in questo caso a condividere il segreto sono solo 2 persone.

3) Per ricostruire il messaggio, Alice e Bob devono cooperare sommando i


frammenti:

M = (M – r) + r

Un problema fondamentale è rappresentato dall'impossibilità di scegliere


un numero intero casuale r, in modo tale che tutti i possibili r siano
numeri interi equiprobabili.

Perciò scegliamo un intero n più grande di tutti i possibili r consideriamo


tutti i possibili r come numeri interi in mod n.

Adesso esaminiamo il caso di divisione del messaggio M in tre persone: Alice,


Bob, Carlo. Scegliamo due numeri casuali, r ed s mod n e diamo:

1) Ad Alice assegniamo (M – r – s) mod n

2) A Bob assegniamo r

3) A Carlo assegniamo s

In questo caso a condividere il segreto sono solo tre persone.


4) Per ricostruire il messaggio devono cooperare tutti e tre sommando i
frammenti:

M = M - r – s + r + s (mod n)

In generale se vogliamo dividere il segreto M tra m persone dobbiamo scegliere:

1) (m – 1) numeri casuali:

r1, …, r(m - 1) mod n

e darne uno ciascuno alle (m – 1) persone

2) All'ultima persona daremo:

M – SUM(i = 1, (m – 1)) ri mod n

Questo schema ha un problema fondamentale:

il suo limite è costituito dal fatto che lo schema presupponga che tutte le
persone che vogliono leggere il segreto siano presenti alla consegna delle
chiavi.

Se non ci sono abbastanza persone o se una volta riunite non vengono tutte le
persone che possiedono la chiave, il segreto viene irrimediabilmente perso.

Se questo accade lo schema muta e si utilizza allora uno schema di


condivisione del segreto a soglia.

2) SCHEMI A CONDIVISIONE DEL SEGRETO A SOGLIA:

La soglia viene scelta da colui che possiede il segreto da nascondere. A questo


punto, per ricomporre il segreto bastano minimo tante persone quante decise
dalla soglia (ovvero un sottoinsieme delle persone a cui vengono date
le chiavi).

Il primo ad inventare un protocollo del genere è Shamir.

SHAMIR THRESHOLD SCHEME:

1) Scegliamo:

t = soglia
w = totalità delle persone, con w >= t
p = numero primo sufficientemente grande
M = messaggio rappresentato da un numero mod p
Ovvero il messaggio M è rappresentato da un numero mod p che
vogliamo dividere tra w persone in modo che t di esse siano necessarie
per ricostruire il messaggio.

2) Scegliamo casualmente:

t – 1 interi (mod p)

li chiamiamo:

s1, s2, …..st-1

3) Impostiamo il polinomio che descrive il passaggio di una curva per una


serie di punti:

S(x) ≡ M + (s1 * x) + (s2 * x2) +... + (s t-1 *x t-1


)

di conseguenza il polinomio S(X) nasconde il segreto M.

4) Allora si scelgono le x1, ..., x w mod p (che sono numeri interi, per
comodità piccoli e progressivi) da dare ad ogni persona del gruppo w.

Di conseguenza ogni punto passante dalla curva descritta dal polinomio è


cosi composto:

pi = (xi , yi), con 1 <= i <= w

dove:

yi ≡ S(xi) mod p

Si continua dal primo punto fino alla generazione del punto:

p1, p2, … , p w

ovvero fino alla generazione di tutti i punti passanti per la curva descritta
dal polinomio S(X).

Il numero p è noto a tutti, ma Il polinomio S(x) è ovviamente segreto e lo


conosce solo chi detiene il segreto.

5) Una volta generati tutti i punti, a tutte le w persone do una


informazione, ovvero assegno ad ognuno un punto passante per la curva
descritta dal polinomio, assegnando ad ognuno la rispettiva coppia:

< x i , yi >

In questo modo siamo riusciti a nascondere il messaggio distribuendo la


chiave fra le w persone.
Alla lettura del segreto però si presentano t persone, non le w originali, e
ciascuna presenta il proprio punto, ovvero la propria coppia:

< x i , yi >

Supporremo che siano:

< x1 , y1 >, …, < x t , y t >

Per ricostruire il messaggio M, la chiave si calcola per coalizione, scrivendo un


sistema lineare. Il polinomio S(X) ha grado (t – 1), pertanto ad esempio la
k-esima persona sa che:

yk = M + (s1 * x1) + (s2 * x2)2 + … + (sk * xk)(t – 1) mod p, con 1 <= k <= t

perché possiede il punto pk, ovvero la coppia < xk , yk >.

Tutti gli altri ragioneranno alla stessa maniera.

Dopo aver scritto le t equazioni, le si mette a sistema in un tot di incognite. Il


sistema è in forma matriciale, ed ha una sola soluzione a seconda del valore del
determinante.

Se indichiamo s0 = M, possiamo scrivere:

Di conseguenza, si moltiplica matrice fatto con:

x1, …, x (t - 1)

e la si moltiplica per il vettore

s0, …, S t

e si ottiene il vettore risultante.

Per come è fatta la matrice principale del sistema, è una matrice di


Vandermonde, allora il suo determinante è facilmente riconoscibile e la
soluzione del sistema esiste è unica mod p se la matrice è diversa da 0 mod p.
Difatti, il determinante è 0 mod p solo se due degli x i , coincidono con mod p
(questo è il motivo per cui abbiamo bisogno di p primo).
Se si utilizza il polinomio interpolatore di Lagrange, bastano solo tre
persone per trovare il segreto.
Curve elittiche
Presentate negli anni ’80, possono essere usate sia per difendersi che per attaccare
crittosistemi come RSA.

Il vantaggio principale che introducono è il fatto che a parità di sforzo computazionale


utilizzano meno bit nella chiave rispetto RSA e per questo sono più veloci a criptare e
possono essere utilizzate anche quando le risorse a disposizione sono limitate.

Una curva ellittica è una curva che non ha niente a che vedere con le ellissi (ma anzi
ha a che fare con gli integrali ellittici) e la sua forma più generica, poiché ne ha
diverse a seconda degli usi, è descritta dall'equazione:

E.C. y2 = x3 + ax2 + bx + c

Tuttavia a noi non interessa più di tanto l'espressione matematica della curva in sé,
ma l'insieme E.C. formato dalle coppie (x, y) tali per cui:

ogni x ed ogni y appartengono ad un insieme k di numeri la cui natura viene


stabilita in partenza, ovvero R, N, Z. L'insieme k di numeri è definito dai numeri
interi mod p, di conseguenza il dominio di appartenenza delle curve ellittiche
può essere:

R mod p, N mod p, Z, mod p, ecc...

Esempio:
Se decidiamo di lavorare in modulo p = 5 e prendiamo la E.C. scritta sopra
possiamo calcolarci tutti i punti che soddisfano l'appartenenza alla nostra
curva andando a sostituire i valori 0, 1, 2, 3 e 4 alla x.

Per convenzione si aggiunge anche il punto (∞,∞).

Si consideri che le radici ellittiche sono equazioni con almeno tre radici minimo.

LEGGE DELL’ADDIZIONE:

Tale legge è valida per i punti appartenenti ad una curva ellittica.


Tale legge ci consente di prendere due punti qualsiasi p1 e p2 appartenenti alla
curva e di sommarli assieme per ottenere p3 che sarà a sua volta posizionato
sulla curva.

Si sommano ora:

p1 + p2 = p3

ovvero calcolo le coordinate di p3.


Per sommare due punti sulle curve ellittiche si procede come segue:

1) Si calcola l’equazione della retta passante per i due punti P1, P2

2) La retta ottenuta intersecherà la curva ellittica in un punto Q

3) Il punto p3 avrà la stessa ascissa del punto Q, quindi la stessa x, ma


ordinata opposta, quindi la stessa y cambiata di segno, ovvero:

Q = (x, y) => P3 = (x, -y)

Ci sono ora due casi: p1 ≠ p2 e p1 = p2.

1) CASO P1 ≠ P2:

Se i due punti non coincidono posso calcolare l’equazione della retta


passante per due punti nel seguente modo:

Data una curva ellittica generica:

y2 = x3 + ax2 + bx + c

e due punti p1 = (x1 , y1) e p2 = (x2, y2) per ottenere p3 = (x3, y3):

1) Scriviamo l'equazione della retta passante per i punti p1 e p2:

(x2 – x1) * (y – y1) - (y2 – y1) * (x – x1) = 0 =>

(y – y1) / (y2 – y1) = (x – x1) / (x2 - x1)

2) Per trovare il punto Q di intersezione devo mettere a sistema


l'equazione della retta con quella della curva elittica, e risolvere il
sistema.

3) Il risultato ottenuto mi permette di ricavare il punto Q. Invertendo poi il


valore di y del punto Q otteniamo il punto p3.

2) CASO P1 = P2:

Se i due punti non coincidono posso calcolare l’equazione della retta


tangente alla curva ellittica passante per il punto p1.

Data una curva ellittica generica:

y2 = x3 + ax2 + bx + c

e due punti p1 = (x1 , y1) e p2 = (x2, y2) per ottenere p3 = (x3, y3):
1) Calcoliamo il coefficiente angolare m della retta per cui si fa la derivata
della E.C.

2) Scriviamo l’equazione della retta tangente alla curva ellittica passante


per il punto p1:

(y – y1) = m * (x – x1)

3) Per trovare il punto Q di intersezione devo mettere a sistema


l'equazione della retta con quella della curva elittica, e risolvere il
sistema.

4) Il risultato ottenuto mi permette di ricavare il punto Q. Invertendo poi il


valore di y del punto Q otteniamo il punto p3.

REGOLA DEL PUNTO ALL'INFINITO:

E' l'elemento neutro dell'addizione, è come se si disegnasse una retta


perfettamente verticale.
L'addizione gode delle seguenti proprietà:

1) P + ∞ = P

2) (x, y) + (x, -y) = ∞

3) - (x, y) = (x, -y)

SOTTRAZIONI DI DUE PUNTI:

Per eseguire le sottrazioni di due con le curve ellittiche si procede nel seguente
modo:

Se vogliamo sottrarre (a, b) – (x, y) basta sommare (a, b) + (x,- y)

Cambiando dunque il segno della y si può eseguire una sottrazione con la regola
della somma.

FORMULE GENERALI:

Abbiamo visto alcuni metodo per calcolare la somma di due punti, tuttavia
questi metodi sono un po’ lunghi da eseguire ogni volta per cui esistono le
seguenti formule che velocizzano tutto il processo.

Data una curva ellittica generica:

y2 = x3 + ax2 + bx + c
e due punti p1 = (x1 , y1) e p2 = (x2, y2) per ottenere p3 = (x3, y3):

X3 = m2 – x1 – x2

Y3 = m * (x1 – x3) - y1

dove m:

1) Se P1 ≠ P2 => m = (y2 – y1) / (x2 - x1))

2) Se P1 = P2 => m = (3x12 + b) / 2y1

E' importante ricordare che la legge dell'addizione gode delle proprietà associativa e
commutativa.

Per cifrare le curve ellittiche non si scelgono a caso bensì da una serie
studiate appositamente per essere usate al posto di RSA.

ASPETTI MATEMATICI:

E' importante ricordare che le formule esplicitate poco prima non è detto
funzionino sempre, specialmente se si lavora per esempio nei numeri interi e si
ottiene, tramite le suddette, un numero frazionario.

Per risolvere il problema lavoro in mod p, ma anche in questo caso non è detto
che esista l'inverso di tutti i numeri in tutti i moduli.

1) CIFRARE:

Quando si cifra con le curve ellittiche si mira a nascondere il testo in


chiaro all'interno dei punti della curva stessa. È nel nostro interesse
quindi sapere quanti punti possiede una curva.

In generale una curva ellittica possiede N punti.

Una curva ellittica mod p possiede:

(p / 2) valori positivi tali per cui la sua equazione si verifica, ma


contemporaneamente possiede (p /2) valori negativi altrettanto
validi.

Per questo motivo alla fine ho all'incirca p valori validi ai quali


aggiungo il punto all'infinito per un totale di p + 1 valori.

Possiamo dire che:

N=p+1
Se p è un valore piccolo ho di conseguenza pochi punti sulla curva ellittica
(poiché N coincide per lo più con p + 1) ed è più probabile un attacco a
forza bruta.

Esiste una relazione precisa tra i valori di p ed il numero di punti N


espressa come:

|N – p – 1| < 2 * √p

il che equivale a dire che fissati N e p esiste sempre una curva ellittica in
mod p con quegli N punti se la disuguaglianza vale per N e p.

2) LOGARITMO DISCRETO APPLICATO ALLE E.C.:

Per applicare il logaritmo discreto alle curve ellittiche, basta prendere una
curva ellittica e due punti A e B che appartengono alla stessa.

Quante volte si deve ripetere A per ottenere B?


Ovvero, qual'è il valore di k nell'espressione k * A = B?

Questo è il corrispondente del logaritmo discreto nelle curve ellittiche


infatti è intrattabile riuscire a trovare quante volte ho moltiplicato A.

Di conseguenza, questo è un possibile attacco alle curve elittiche.

Per applicare questo processo bisogna scegliere quindi due punti sulla
curva ellittica, e per fare questo vengono usati dei metodi probabilistici, il
più famoso è quello di Koblitz.

Il testo in chiaro va sempre tradotto numericamente prima di essere


cifrato, anche in RSA. Nelle curve tuttavia non esistono metodi rapidi
per associare ad ogni punto un frammento del testo in chiaro.

Si procede nel seguente modo:

1) Supponiamo di aver scelto N a caso ed abbastanza grande,


composto a sua volta da fattori primi quindi non è un numero primo
a sua volta (N = n = p * q) come per RSA

Ora so che con la mia E.C. sto lavorando in mod n:

y2 = x3 + ax2 + bx + c (mod n)

2) Quando calcolo m coefficiente angolare devo essere certo che


esista il suo inverso nel modulo scelto ma accade solo quando
m ed il modulo sono tra loro coprimi:

ovvero quando il loro MCD(m, n) = 1


se invece MCD(m, n) = a, allora sono sicuro che è un fattore di n.

Allora scelgo un punto P a caso e costringo la curva a passare per


questo punto, calcolando di conseguenza la c di E.C. prendendo
come b E.C. un numero a piacimento

3) Sostituisco nell’equazione i valori della x e della y del punto P e il


valore di C e di B e calcolo m

4) Nel calcolo di m, prendo il denominatore del risultato che chiamo


dem e verifico se possa darmi qualche problema, che quindi non
appartiene a mod n, facendo il:

GCD(den, n)

Se GCD(den, n) = 1, allora il denominatore ha un inverso in mod n,


di conseguenza l'm utilizzato non mi da fastidio.

Allora se m non mi da fastidio devo scegliere un altro P e per farlo


lo sommo a se stesso per ottenere 2p

Ripeto il calcolo di m:

Moltiplico il numeratore della m ottenuta prima per l’inverso


ottenuto trovato e ottengo il nuovo valore di m mod n

Se non mi da nessun problema calcolo 3p ed avanti così fino a


quando non mi capita un m con un denominatore apparentemente
senza inverso in mod n, ovvero:

GCD(den, n) = a

ovvero è uno dei fattori che compone n.

5) Per scoprire qual'è l'altro mi basta dividere n per il valore a di


MCD.

È così che trovo tutti i componenti della chiave n del sistema della E.C.

Il valore di a si trova sempre? In generale si, dipende tuttavia da quante


somme p devo fare. Se ho fortuna me ne bastano poche, se sono
sfortunato potrei farne a centinaia. Questi sono conti molto oneresi in
termini di risorse computazionali e di tempo.

Dal punto di vista grafico calcolare una curva mod n è come calcolarne
due una mod q e l'altra mod p, tuttavia le due curve distinte possono
andare all'infinito in due momenti diversi (quindi trovano l'm che da
problemi in due momenti diversi).

Piuttosto che calcolare la somma di p volta per volta scelgo fin da subito
un valore di p molto alto (se non trovo il valore di p giusto entro gli 80,
non ha senso che faccia la somma fino ad 80, ma posso prendere
direttamente 80). Scelgo quindi p grande.

3) NUMERI LISCI:

Un numero N è definito numero liscio quando è composto solo da numeri


primi molto piccoli. Tale numero N è detto B-liscio se i numeri primi di
cui è composto sono tutti minori di una certa soglia B scelta da me.

Sia che m è il numero che mi da “rogne” ed è il primo tra tutti quelli che
potrebbero darmi fastidio anche in futuro se continuassi a sommare p (se
ho sommato p 8 volte → m = 8).
Tale numero divide il numero totale di punti che possiede la curva → N/m
ma N è molto grande.

E’ dimostrato che prendere dei valori alti per i punti a caso aumenta la
probabilità che i punti facciano parte della curva ellittica.

Considero che la probabilità che N sia un numero liscio è molto alta:


se N è liscio e (N / m) allora anche m è un numero liscio.

Ma se m è liscio posso scegliere 1000!p per fare i conti perché posso


essere sicuro che tale valore contenga tutti i valori che dividono anche m,
quindi è multiplo di m e se m da problemi lo darà anche ogni suo multiplo.

A questo punto sono sicuro di trovare il valore per cui andare all'infinito.

Solitamente non si fa uso di curve ellittiche con radici multiple per evitare di
complicarne l'utilizzo, ma nulla vieta che se ne possano usare a piacimento a
seconda del bisogno.

Comunque sia, si utilizzano solamente curve forti ed una curva è definita forte
quando è il NIST a dirlo.

È stato appunto l'ufficio americano a stilare una lista di curve ellittiche testate
da loro e selezionate a scopo crittografico: le curve sono 15, 10 delle quali
lavorano in:

mod 2^N con N > 150.

ASPETTI INFORMATICI:

Utilizzare le curve ellittiche per cifrare è veramente molto semplice.


Si tratta di sfruttare i metodi tradizionali trasportati però nel regno delle curve
ellittiche.
1) ELGAMAL APPLICATO ALLE E.C.:

Per criptare si utilizza l'algoritmo di ElGamal tradizionale ma lo si applica


alle curve ellittiche. Si sa che alla base del funzionamento dell'algoritmo
di ElGamal tradizionale c'è lo sfruttamento del problema del logaritmo
discreto, così anche nel campo delle curve ellittiche si applica il problema
del logaritmo discreto ma inerente alle curve ellittiche stesse.

Come sempre ci sono due attori, Alice e Bob, che vogliono comunicarsi un
messaggio e lo vogliono cifrare.

1) Alice sceglie:

una curva ellittica EC,


un numero primo p,
un punto a appartenente alla curva,
un numero casuale n che terrà poi segreto

2) Alice allora calcola:

b=a*n

quindi calcola b come n volte il punto a (è qui che sfruttiamo il logaritmo


discreto applicato alle curve ellittiche)

3) Alice spedisce a Bob:

(E.C., a, b)

senza p perché p è già intrinseco in EC essendo il modulo della curva

4) Bob scarica il pacchetto di Alice, tuttavia ha ancora m che è il


messaggio in chiaro e lo cela all'interno di un punto di E.C. chiamato x

5) Bob sceglie un numero k casuale segreto e calcola:

y1 = k * a

e:

y2 = (k * b) + x

spedendo poi a Alice la coppia (y1, y2)

6) Alice scarica il pacchetto di Bob. Tale coppia contiene il messaggio m


ed ad Alice non resta altro da fare che recuperarlo e calcola:

y2 – (n * y1) = x

Alice riesce cosi a vedere il messaggio di Bob.


DIMOSTRAZIONE:

Volendo verificare che Alice abbia ricevuto informazioni corrette:

y2 – (n * y1) = (x+ k * b) – n * (k * a)

così sostituisco ad y1 ed ad y2 i loro valori attribuiti da Bob.


Allora poiché:

b=a*n

riscrivo sopra come:

(x+ k * b) – n * (k * a) =

= (x+ k * b) – b * k = x

Il vantaggio nell'utilizzo di una curva ellittica per cifrare sta nel fatto che
non esistono attacchi validi per gli algoritmi tradizionali che funzionino
anche sulle curve ellittiche:

in questa maniera l'algoritmo di ElGamal per le curve ellittiche risulta


inattaccabile. In più, è facilitato il lavoro computazionale risultando più
rapido e leggero e meno oneroso per la macchina.

2) DIFFIE-HELLMAN APPLICATO ALLE E.C.:

Anche in questo caso si sfrutta un algoritmo tradizionale adattandolo


al caso delle curve ellittiche. Con questo metodo si vuole far in modo
di scambiare una chiave in modo sicuro tra i nostri soliti due attori,
Alice e Bob.

1) Alice e Bob scelgono congiuntamente (oppure uno sceglie e fa sapere


all'altro, comunque entrambi sono a conoscenza delle stesse
informazioni):

una curva ellittica EC,


un numero primo p,
un punto G per cui passa la curva,
un b perché la curva è scelta come nel caso precedente forzandola
per il punto G

2) Alice e Bob scelgono un punto della curva ellittica ciascuno e


ottengono cosi:

Alice → Na

Bob → Nb
3) Alice calcola:

Na * G

e spedisce il risultato a Bob.

4) Bob calcola:

Nb * G

e spedisce il risultato ad Alice.

Cosi si scambiano i due valori (ed è qui che entra in gioco il logaritmo
discreto nel caso delle curve ellittiche)

5) In seguito Alice calcola:

Na * (Nb * G)

6) Mentre Bob calcola:

Nb * (Na * G)

Cosi ottengono entrambi la chiave pubblica.

Potrebbero piacerti anche