generazione di numeri pseudocasuali

Transcript

generazione di numeri pseudocasuali
Esame di laboratorio di crittografia
Lorenzi Stefano
matricola 754752
GENERAZIONE
DI NUMERI
PSEUDOCASUALI
1
Indice generale
GENERAZIONE DI NUMERI CASUALI..........................................................................................3
Introduzione.....................................................................................................................................3
ALGORITMI DI GENERAZIONE DI NUMERI PSEUDOCASUALI.............................................5
Panoramica sugli algoritmi esistenti................................................................................................5
Metodo della congruenza lineare.....................................................................................................5
Ansi X9.17.......................................................................................................................................7
Blum Blum Shub.............................................................................................................................8
LibMTPRNG...................................................................................................................................9
SOFTWARE.......................................................................................................................................10
Presentazione del software.............................................................................................................10
Attacchi agli algoritmi........................................................................................................................13
Attacco all'algoritmo a congruenza lineare....................................................................................13
Attacco all'algoritmo Ansi X9.17..................................................................................................13
Input-Base attacks.....................................................................................................................13
Crittoanalisi...............................................................................................................................14
Attacco a Blum Blum Shub......................................................................................................14
Bibliografia.........................................................................................................................................15
2
GENERAZIONE DI NUMERI CASUALI
Introduzione
Un generatore di numeri casuali è uno strumento capace di fornire una sequenza di
numeri casuali, ovvero non deterministici. Questi numeri sono idealmente infiniti e non
sono influenzabili da alcun fattore esterno.
Tali numeri ricoprono un ruolo importante nella crittografia, basta pensare agli schemi di
autenticazione reciproca e nello scambio delle chiavi, dove per prevenire attacchi a replay
dei pacchetti vengono utilizzati dei numeri “nonce”. Un altro esempio di tale importanza è
la generazione della chiave pubblica nell'algoritmo RSA.
Queste applicazioni danno origine a due requisiti distinti e non necessariamente
compatibili:
●
●
Casualità
Imprevedibilità
Casualità
Un elaboratore non ha la possibilità di generare una sequenza casuale, bensì l’unico
modo è utilizzare opportuni algoritmi che generano numeri apparentemente casuali.
Questi vengono, quindi, chiamati numeri pseudo-casuali, poiché venendo a conoscenza
dell’algoritmo e del seme (primo elemento) utilizzati è possibile determinare la sequenza
che verrà generata.
Tali algoritmi per essere considerati “generatori casuali” in senso statistico devono avere
due caratteristiche:
●
●
Distribuzione uniforme: Generando una quantità elevata di numeri, ognuno di essi
deve apparire con una frequenza simile.
Indipendenza: non deve essere possibile determinare l'ennesimo numero,
guardando gli n-1 numeri.
Se è semplice verificare se una sequenza segue o meno una distribuzione uniforme, non
è altrettanto semplice dimostrarne l'indipendenza. Per definire l'indipendenza è possibile
eseguire diversi test che aiutano ad avere una certa possibilità che i numeri generati siano
indipendenti.
Nell'ambito della crittografia, la progettazione di algoritmi di numeri che sembrano
statisticamente casuali ricoprono un ruolo fondamentale: un esempio è la generazione di
numeri primi nella creazione della chiave pubblica in RSA. Per la generazione di tali
numeri, un approccio a forza bruta prevede la divisione del numero N per ogni interno
dispari minore di  N . Ma se N è un numero molto grande (nell'ordine di 10150), i tempi
richiesti sarebbero troppo alti, e questa è una situazione piuttosto comune nella
crittografia.
3
Per risolvere tale problema esistono algoritmi in grado di verificare se un numero è primo,
ad esempio producendo una sequenza di numeri casuali ed eseguendo semplici calcoli.
Se tale sequenza è sufficientemente lunga, sarà possibile determinare con una buona
sicurezza se un numero è primo.
Imprevedibilità
Se da una parte è importante generare numeri apparentemente casuali, dall'altra è
fondamentale che, data una sequenza, sia impossibile determinare i numeri successivi.
In altre parole, ogni numero generato è statisticamente indipendente dai precedenti.
Prendiamo come esempio due serie di 1 e 0.
0, 1, 0, 1, 0, 1, 0, 1, 0, 1...
1, 1, 0, 1, 0, 1, 1, 0, 0, 1, ...
Apparentemente si è portati a definire la prima sequenza deterministica, poiché si
riconosce una certa periodicità o un algoritmo capace di generarla; la seconda sembra
essere “più casuale” e non si trova alcuna regola capace di formarla (quindi non è
prevedibile).
4
ALGORITMI DI GENERAZIONE DI NUMERI
PSEUDOCASUALI
Panoramica sugli algoritmi esistenti
Esistono diversi algoritmi per la generazione di numeri pseudo-casuali, che si
differenziano per il tipo di algoritmo usato.
Alcuni si basano su calcoli matematici, altri su sistemi crittografici. Nella quasi totalità, essi
producono una sequenza di numeri interi uniformemente distribuiti tra 0 e un certo valore
massimo, oppure di numeri reali tra 0 e 1. Questi ultimi si possono sempre ottenere dai
primi semplicemente dividendo per il valore massimo, come ad esempio alcune librerie dei
linguaggi di programmazione.
Prima di essere usato, un generatore deve essere inizializzato assegnando un opportuno
valore a un parametro numerico, o gruppo di parametri, che viene chiamato seme (in
inglese seed). Ogni volta che si usa lo stesso seme, si otterrà sempre la stessa identica
sequenza.
Un'attenta analisi matematica è richiesta per assicurare che i numeri generati abbiano le
necessarie proprietà statistiche. Robert R. Coveyou dell'Oak Ridge National Laboratory ha
intitolato un articolo: "La generazione dei numeri casuali è troppo importante per essere
lasciata al caso."
Metodo della congruenza lineare
Tale metodo permette, dato un valore iniziale x0 detto seme, di ottenere una sequenza di
numeri pseudo-casuali mediante l’applicazione ripetuta della seguente formula:
xi+1 = (a * xi + c) (MOD m)
dove:
a
c
m
xi
è un coefficiente intero positivo detto moltiplicatore
è un coefficiente intero non negativo detto incremento
è un coefficiente intero positivo detto modulo
è il generico numero della sequenza
Il metodo prende il nome dalla seguente definizione:
due numeri x e y si dicono congrui modulo m, e scriveremo x ≡ y (mod m), se essi
differiscono per un multiplo intero di m, ossia se x (mod m) ≡ y (mod m).
Il metodo è detto moltiplicativo se c=0, misto se c ≠ 0. Se a=1, il metodo è detto additivo.
Facciamo degli esempi: partiamo attribuendo le seguenti assegnazioni:
5
a=3
c=5
m=11
Se X0=3, la sequenza che si ottiene applicando la formula della congruenza modulare è [3,
3, 3, 3,], ossia una sequenza assolutamente non casuale.
Le cose cambiano se scegliamo X0=1; in questo caso, la sequenza ottenuta è la seguente:
1, 8, 7, 4, 6, 1, 8, 7, 4, 6, 1, ...
Possiamo notare che i primi 5 numeri vengono riprodotti interamente.
Infine, se X0=2, si ottiene:
2, 0, 5, 9, 10, 2, 0, 5, 9, 10, 2, ...;
Anche in questo caso otteniamo una sequenza di 5 numeri ripetuti.
Se modifichiamo il valore di a assegnandogli il valore 12, e poniamo X0=1, ottieniamo:
1, 6, 0, 5, 10, 4, 9, 3, 8, 2, 7, 1, 6, 0, 5, ...
Essa è una sequenza di periodo 11 e cioè pari a m, e senza ripetizione di numeri.
In questo ultimo esempio è interessante osservare che non solo generiamo 11 numeri tutti
diversi e che copriamo l'intero periodo, ma la sequenza si ripete.
Questo ci permette di poter generare molti numeri con una distribuzione uniforme. Quindi
possiamo sostenere che questo algoritmo ha le seguenti proprietà:
1. l'algoritmo genera l'intero periodo di numeri, ossia prima di ripetersi ha generato
tutti i numeri compresi tra 0 e m.
2. La sequenza generata è apparentemente casuale.
3. I calcoli sono eseguiti facilmente da un calcolatore.
Come abbiamo potuto osservare, questo algoritmo funziona bene se sono stati scelti dei
parametri opportuni.
Per quanto riguarda l'implementazione di questo algoritmo su un elaboratore è importante
impostare m al valore del massimo intero rappresentabile da quel processore, in modo
tale che la sequenza generata abbia un periodo molto ampio, ricordando che il bit più
significativo rappresenta il segno. Per processori a 32 bit, un valore utile di m è 231-1.
Per rappresentare tutto il periodo occorre però fare attenzione alla scelta di a e c. Si può
dimostrare però che se m è primo e c = 0, allora vengono generati m-1 valori con la sola
assenza del valore 0 (231-1 è un numero primo).
Purtroppo degli oltre 2 miliardi di numeri a disposizione, solo pochi possono essere scelti
per il parametro a (un valore spesso utilizzato per a è 75 = 16807)
Da tutto ciò si possono ricavare le seguenti osservazioni:
●
La lunghezza massima raggiungibile dalla sequenza generata senza ripetizione
6
●
●
●
vale m
Particolari scelte di a e c possono ridurre notevolmente la lunghezza utile della
sequenza
Il valore di X0 (seme) può essere determinante dalla lunghezza della sequenza
E' fondamentale che il periodo sia il più ampio possibile per rendere l'algoritmo più
sicuro da eventuali attacchi.
E’ allora necessario individuare dei criteri per assegnare ad a, c, m e al seme dei valori in
modo che la sequenza riprodotta sia la più lunga possibile.
Alcuni studiosi hanno approfondito tale aspetto e hanno individuato i seguenti criteri
necessari e sufficienti che garantiscono l'ottimalità del metodo:
1. I parametri c e m devono essere coprimi cioè MCD(c,m) = 1
2. Ogni divisore primo di m deve dividere (a-1)
3. Se m è multiplo di 4, anche (a-1) lo deve essere.
Questi studiosi hanno individuato quindi i seguenti valori nel rispetto dei suddetti criteri:
KNUTH
m = 2 31; a = int (π * 10 8) ; c = 453806245
GOODMAN e MILLER
m = 2 31 -1; a = 7 5 ; c = 0
GORDON
m = 2 31; a = 5 13 ; c = 0
LEORMONT e LEWIS
m = 2 31; a = 2 16 + 3 ; c = 0
Ansi X9.17
E' uno dei generatori più forti dal punto di vista crittografico. Esso fa uso del Triple-Des in
modalità EDE (Encrypt-Decrypt-Encrypt); come input ha un numero random e segreto
(generalmente la data e ora del dell'elaboratore) di 64 bit. Infine, ha un valore intero m
(random) come seme, e due chiavi per il triple-des.
La robustezza di questo algoritmo sta nel fatto che è usato il triple-des per tre volte ed una
chiave da 112 bit: questo equivale a nove crittografie DES. Quindi, un ipotetico attaccante
dovrebbe violare una grossa quantità di dati.
Tale algoritmo può essere rappresentato nel seguente modo
R = E[E(T) XOR V]
V = E[E(T) XOR R]
dove
●
E() = è il TripleDes
●
DTi = Timestamp
●
Vi = Initialization Vector
●
Ri = random number to be generated
7
Blum Blum Shub
Questo algoritmo, molto usato, è sostanzialmente un generatore di bit, ed ha dato forse la
più forte prova di potenza crittografica.
Il funzionamento è il seguente:
1. Bisogna generare due numeri p e q, numeri primi (molto grandi) diversi tra loro e
ciascuno congruente a 3 modulo 4 (ossia p e q divisi per 4 avranno resto 3)
2. Si imposta n come p*q
3. Si seleziona il seme,ossia un numero random s, tale che 1<=s<=n-1. Inoltre s deve
essere coprimo con n [ossia gcd(s,n)=1]
4. Quindi x0 ←s2 mod n.
5. Xi = (Xi-1) 2 mod n
6. Bi = xi mod 2
7. Concatenando i bit ottenuti al punto precedente, si genera un numero della
dimensione desidarata.
Come per l'algoritmo a congruenza lineare questo algoritmo per essere sicuro deve avere
un valore di n molto grande, nell'ordine di 1024 bits.
8
LibMTPRNG
Matthew Davis e Sameer Niphadkar propongono un algoritmo senza seed, basato sul
multithreading e sul non-determinismo.
Il loro ragionamento si basa sul fatto che lo scheduling dei thread all'interno di un processo
è abbastanza casuale, non esiste una priorità e lo stato di running può dipendere da una
molteplicità di eventi. Questo non-determinismo è intensificato dai moderni calcolatori
multiprocessore, dove più thread possono girare in parallel. In sostanza, non è prevedibile
un modello di comportamento, a meno che lo scheduler non eserciti una grande influenza.
Da queste premesse gli autori hanno scritto LibMTPRNG (Multithreaded Pseudo-Random
Number Generator Library), una libreria statica sulla falsariga di rand(), che è definita nello
standard C99.
Si basa su un intero a 32 bit e si associano 2 thread per ogni bit; quando viene richiesto un
numero pseudo-casuale, viene rilasciato un mutex su un oggetto condiviso e si fanno
partire i primi 32 thread, garantendo un accesso atomico attraverso meccanismi di mutual
exclusion.
Ciascun thread manipola un solo bit e incrementa un contatore, il quale stabilirà la fine del
processo e quindi la disponibilità del numero pseudo-casuale.
Una descrizione più dettagliata si trova in un articolo tecnico pubblicato ial seguente
indirizzo: http://www.ddj.com/hpc-high-performance-computing/216900024, articolo che
costituisce, a conoscenza del sottoscritto, l'unica documentazione disponibile, oltre
naturalmente ai sorgenti.
I test di effettiva casualità sono stati condotti seguendo le indicazioni di Some Difficult-topass Tests of Randomness, su sistemi Linux e Solaris. I risultati non sono eccezionali, ma
gli autori sostengono che indagando più a fondo i meccanismi paralleli e alcuni eventi,
come le race condition, si potrà migliorare questa interessante idea.
9
SOFTWARE
Presentazione del software
Utilizzando gli algoritmi presentati in questo lavoro, ho implementato un software che
genera grandi quantità di numeri pseudo casuali.
Inoltre, visto che il software è stato implementato in Java, ho utilizzato anche il generatore
nativo di numeri casuali di questo linguaggio, ed ho voluto vedere come tali algoritmi
funzionano nella pratica.
I parametri che ho voluto osservare sono:
●
●
Se i numeri hanno una distribuzione uniforme
Il tempo richiesto nella generazione di queste sequenze
Come possiamo vedere dall'immagine, è possibile configurare dei parametri, in
particolare:
10
●
●
●
●
Il numero minimo
il numero massimo
La quantità dei numeri da generare
Inoltre per il metodo a congruenza lineare è possibile variare i parametri di
input(modulo, moltiplicatore e incremento)
E' evidente che qualora decidessi di impostare un range compreso tra 0 e 231 – 1, avrei
sempre una distribuzione uniforme. Con range più piccoli, ad esempio tra 0 e 9, il numero
verrebbe generato nel seguente modo: X = N mod 10, dove N è il numero generato
dall'algoritmo scelto. Questo comporta che si ottiene una distribuzione uniforme solo dopo
aver generato una lunga sequenza si numeri: in altre parole, più il range è grande, meno
numeri occorrono per avere una distribuzione uniforme.
Come possiamo vedere dalle immagini, su range piccoli occorrono almeno 100.000
numeri per avere una distribuzione uniforme. Questo valore è più o meno uguale per tutti
gli algoritmi provati.
Figura A : 1000 numeri
Figura B: 100.000
Figura C: 1.000.000
Il dato invece che cambia molto è quello inerente al tempo per generare questi numeri.
Nella tabella seguente sono riportati i tempi necessari utilizzati dal mio calcolatore per la
generazione di un milione di numeri:
Congruenza lineare
98 millisecondi
Ansi X9.17
32,5 secondi
Blum Blum Shub
13 secondi
Java Random
134 millisecondi
Java Security
2187 millisecondi
È evidente come la complessità del calcolo incida sul tempo. Se da una parte il metodo
della congruenza lineare è molto veloce, dall'altra è anche il meno sicuro: infatti, tale
sistema dipende principalmente dal seme, e se un ipotetico attaccante volesse violare tale
11
algoritmo dovrebbe andare alla ricerca di un solo valore. Dall'altro lato, il metodo Ansi
X9.17, seppur decisamente più lento, per venire attaccato necessita di conoscerne il
seme, il timestamp, e 2 chiavi del triple des (ben 4 valori).
Anche la differenza tra le 2 librerie Java è notevole (ricordo che la libreria Random è poca
sicura, è basata sull'algoritmo a congruenza lineare con un seme di 48 bit).
Il software è stato sviluppato con la versione 1.6 di Sun Microsystem ed utilzza le librerie
JfreeChart 1.0.12 reperibili all'indirizzo http://www.jfree.org/jfreechart/download.html
La figura sottostante riporta il diagramma UML
12
Attacchi agli algoritmi
Attacco all'algoritmo a congruenza lineare
Se l'attaccante conosce il valore di m e 3 numeri consecutivi, allora si può sferrare il
seguente attacco:
●
●
●
Xi+1 ≡(aXi + c) mod m
Xi+2 ≡(aXi+1 + c) mod m
Xi+2 - Xi+1 ≡(aXi+1 + c - aXi - c) mod m ≡ a(Xi+1 - Xi) mod m
Vediamo un esempio con i seguenti dati:
m=9, Xi = 3, Xi+1 = 7, Xi+2 = 0
(0 - 7) ≡a(7-3) mod 9 ← → 4a ≡2 mod 9
Quindi il parametro a sarà 5.
5 * 3 + c ≡15 + c mod 9 ≡6 + c mod 9 ≡ 7 mod 9
Il parametro c = 1.
Ora che siamo a conoscenza di tutti i parametri, sapremo che dopo i numeri 3, 7 e 0 ci
sarà il numero 1, poi il 6, poi il 4,...
Attacco all'algoritmo Ansi X9.17
Sono diversi i modi per attaccare questo algoritmo, ma tutti hanno una complessità
maggiore rispetto all'attacco visto nel paragrafo precedente
Input-Base attacks
Un input-base attacks si verifica quando un utente malintenzionato è in grado di utilizzare
la
conoscenza o il controllo dell'input. Questa tipologia di attacco può essere
ulteriormente suddivisa known-input, replayed-input, e chosen-input attacks.
Un chosen-input attacks può essere pratico contro smart - card e altri sistemi di crittografia
hardware.
Replayed-input attacks sono simili ai precedenti, ma richiedono un meno sofisticacazioni
di controllo da parte del attaccante.
Known-input attacks può essere in ogni situazione in cui alcuni dei elementi di input,
possono essere facilmente prevedibili, ad esempio se viene usato il timestamp di un pc in
rete, i cui orari sono osservabili dall'attaccante.
13
Crittoanalisi
Seppur generalmente viene usato il triple-des in modalità EDE, l'algoritmo di crittografia
potrebbe anche essere diverso, quindi bisogna essere attenti a quale algoritmo si sceglie
e quali conoscenze di crittoanalisi ci sono su quell'algoritmo.
Attacco a Blum Blum Shub
E' decisamente il più complesso da attaccare tra quelli visti, in particolare perché bisogna
fattorizzare n per trovare i valori di p e q, ma come sappiamo la fattorizzazione è uno dei
problemi non ancora risolti efficientemente dalla matematica (come la soluzione del
logaritmo discreto), non a caso molti sistemi di cifratura si basano su tali presupposti
(RSA, El-Gamal). Questo algoritmo però, è un generatore di bit e il numero random è la
concatenazione dei bit generati precedentemente, questo comporta che anche qualora
venga fattorizzato n, ciò non basta, bisogna infatti fattorizzare tante volte n quanti sono il
numero di bit del numero random generato.
14
Bibliografia
●
Critttografia e sicurezza delle reti – William Stallings McGraw-Hill
●
A. Menezes, P, van Oorschot, S. A. Vanstone - Handbook of Applied Cryptography CRC Press 1996 (chap 5)
●
Wikipedia
15