Matematica Discreta I - Matematica e Informatica

annuncio pubblicitario
Matematica Discreta II
Lezione del giorno 31 ottobre 2007
Numeri primi e test di primalità
Nell’implementazione del sistema crittografico RSA vi è la necessità di trovare numeri primi
abbastanza “grandi”, per aumentare la sicurezza del sistema.
Sappiamo che i numeri primi sono infiniti (Teorema di Euclide), ma nella successione dei numeri
naturali essi sono distribuiti in modo irregolare.
Per valutare il numero di primi in un certo intervallo [0,x] della semiretta positiva dell’asse reale,
definiamo, per ogni reale x0 :
(x)= numero dei primi  x
Per esempio (22,3)= {2,3,5,7,11,13,17,19}=8
Non esistono formule algebriche per il calcolo esatto di (x). Per esempio, usando i computers, si è
verificato che :
(1014) = 3.204.941.750.802
(i valori massimi attualmente calcolati sono intorno a 1022).
Nel corso del tempo, i matematici hanno cercato funzioni che “approssimassero” (x). Il risultato
più famoso è il:
Teorema di Hadamard-De La Vallé Poussin.
Considerata la funzione f(x)=x/log(x) (definita per x>0, x1) dove log(x) è il logaritmo neperiano,
π(x)
si ha:
lim
1
x  f(x)
(il teorema si dimostra con metodi analitici).
Quindi, per x abbastanza grande, il rapporto
π(x)
è abbastanza vicino a 1, e in un certo senso
f(x)
f(x)=x/log(x) approssima (x).
Per esempio f(1014)  3.102.103.442.166, da cui
π(1014 )
f(10 14 )
1.033
Come conseguenza del teorema precedente (dopo alcuni ragionamenti probabilistici) si ottiene che
la probabilità che, scelto casualmente un numero naturale x di n cifre (in base 10), esso sia primo è
 1/[nlog(10)].
Tenendo conto che log(10)  2,3, la probabilità che un numero x di n cifre, scelto casualmente, sia
primo è  1/[2,3log(n)]. Per esempio la probabilità che un numero di 100 cifre sia primo è  1/230:
se scegliamo casualmente 230 numeri di 100 cifre, statisticamente dovremmo aspettarci che uno di
essi sia primo.
Quindi per trovare un numero primo di un fissato numero n di cifre (in base 10), si può scegliere
casualmente un numero di n cifre, sottoporlo a un “test di primalità” (vedere sotto) e se il test non è
superato cambiare la scelta del numero, e così via: statisticamente dovrebbero bastare circa 2,3n
tentativi per trovare un numero primo.
Un test di primalità è un algoritmo tale che, dato in input un numero naturale n>1, produca un
output “n è primo” oppure “n è composto” (definendo composto un naturale >1 non primo).
Si distinguono:
- test di primalità deterministici: l’output è “n è primo” se e solo se l’input n è un numero primo
- test di primalità probabilistici: nell’algoritmo vi è la scelta casuale di alcuni elementi, e inoltre se
l’input n è un numero primo allora l’output è sempre “n è primo” (tutti i numeri primi superano il
test), ma se n è composto, l’output può essere sia “n è primo” sia “n è composto”, e la probabilità
che l’output sia “n è primo” (pur essendo n composto) è maggiorata da una costante < 1 conosciuta
a priori e indipendente dall’input n. Se un naturale n>1 supera un test di primalità probabilistico un
numero k di volte (con gli elementi casuali scelti in modo indipendente), la probabilità che il
numero n sia composto si può rendere piccola a piacere (se k è abbastanza grande), quindi si può
accettare che n sia effettivamente primo, con una bassa percentuale di errore.
Il primo test ingenuo di primalità è il test (deterministico) che verifica, per k=2,….,n-1, se esiste un
k divisore non banale di n: se k esiste l’output è “n è composto”, se k non esiste l’output è “n è
primo”.
L’algoritmo consiste di (n-2) divisioni, quindi il numero di operazioni è <n: se t è il numero di cifre
di n (per esempio in base 2) si ha 2t-1n<2t, e il numero di operazioni è <n<2t, quindi è un algoritmo
di complessità esponenziale.
Questo test si può rendere più efficiente osservando che se esiste un divisore non banale del numero
composto n, allora esiste certamente un divisore non banale di n che sia  n (infatti se per assurdo
fosse n=bc con b,c> n , si avrebbe n>( n )2, contraddizione).
Quindi nel test precedente si può limitare la ricerca ai valori k con 2k n : il numero di divisioni
in questo caso è < n < ( 2 ) t , quindi anche questo algoritmo ha complessità esponenziale.
Un altro test di primalità deterministico segue dal:
Teorema di Wilson.
Sia n> 1 un naturale . Allora: n è primo  (n-1)!-1 (mod n).
Dimostrazione:
(): Consideriamo il gruppo moltiplicativo Zn* degli elementi invertibili di Zn.
Se n è primo, n è coprimo con tutti i numeri 1,2,…,n-1 (perché non sono multipli di n), dunque Zn*
= {[1], [2], ….., [n-1]}.
Calcoliamo il prodotto di tutti gli elementi di tale gruppo:
[1][2] …..[n-1] = [12 …..(n-1)] = [(n-1)!].
In tale prodotto, sfruttando la proprietà commutativa, possiamo accoppiare ogni elemento [i] con il
suo inverso [i]-1 (nel caso in cui [i][i]-1) ottenendo per ogni tale coppia un prodotto =[1]: al termine
di tale semplificazione il prodotto precedente si riduce a quello dei soli fattori [i] tali che [i]=[i] -1,
cioè tali che [i]2=[i2]=[1].
Ma per un tale i si ha n(i2-1), n(i+1)(i-1), quindi (essendo n primo) n(i+1) oppure n(i-1),
ossia i1 (mod n) oppure i-1 (mod n). Si conclude che:
[(n-1)!]=[1][-1]=[-1] , da cui la tesi.
(): Sia (n-1)!+1=kn, con k intero. Se per assurdo esistesse un divisore non banale d di n, con
1<d<n, tale d sarebbe divisore di (n-1)! (perché d è uno dei fattori del prodotto (n-1)!) dunque d
sarebbe divisore di kn-(n-1)!=1 , contraddizione perché d>1.
Nota: la condizione (n-1)!-1 (mod n) del Teorema di Wilson equivale a (n-1)!modn=(n-1) (in
quanto -1(n-1) (mod n)).
Il Teorema di Wilson permette di costruire un test di primalità deterministico:
1) in input il naturale n>1
2) si calcola la riduzione (n-1)!modn (si può per esempio costruire la successione y1,y2,…,yn-1
ponendo y1=1, e per i>1 yi=(iyi-1)modn, ottenendo alla fine yn-1=(n-1)!modn): se (n-1)!modn=(n-1)
si esce con output “n è primo”; altrimenti si esce con output “n è composto”.
Nel passo 2), il calcolo di (n-1)!modn comporta l’esecuzioni di un numero di operazioni (prodotti e
divisioni per la riduzione modulo n) che è <2n=2t+1 (se t è il numero di cifre di n in base 2), dunque
anche questo algoritmo ha complessità esponenziale.
L’unico test di primalità deterministico di complessità polinomiale attualmente esistente è il test
AKS (2003), la cui trattazione esula dagli scopi del corso.
Esponiamo ora un esempio di test di primalità probabilistico: il test di Rabin-Miller.
Esso si applica ad un input n>1 naturale dispari (non è una restrizione sostanziale perché un
naturale pari è sempre composto, tranne nel caso n=2).
I passi dell’algoritmo del test di Rabin-Miller sono:
1) in input il naturale n>1 dispari
2) si calcola la massima potenza 2t di base 2 ed esponente t>0 tale che 2t sia divisore del numero
pari n-1, e si scrive: n-1=2tk, con k>0 naturale dispari (in questo passo si effettuano t divisioni per
2 fino ad ottenere un quoziente dispari)
3) si sceglie casualmente un intero a con 2an-1 (detto base)
4) si calcolano (con l’algoritmo dell’esponenziazione modulare) le riduzioni delle t potenze di base
j
a ed esponente k, 21k, 22k, ….. , 2t-1k:
a 2 k modn
5) se è verificata almeno una delle seguenti condizioni:
per j=0,1,….,t-1
j
ak1 (mod n) oppure a 2 k modn = n-1 per qualche j=0,1,….,t-1
si esce con output ”n è primo”, altrimenti si esce con output “n è composto”
Dobbiamo naturalmente verificare che un input n primo superi sempre il test con output “n è
primo”, e stabilire qual è la costante che maggiora la probabilità che un input composto n superi
egualmente il test.
Scarica