Un metodo diretto per il calcolo di grandi numeri primi è il seguente:
genera M di k bit a caso // viene generato un numero di M di k bit (casuale)
for(i = 2; i * i <= M; i++){
if(M % i == 0)
goto 1 // al passo 1: "genera M di k bit a caso", M non è primo
}
return M // M è primo
C
Dopo che viene generato il numero
Se
a
Il ciclo si ferma quando la
Altra domanda potrebbe essere, come mai non vengono controllati tutti i divisori fino a
Secondo il teorema di Euclide esistono infiniti numeri primi.
Dimostrazione:
la dimostrazione procede per assurdo.
Per assurdo diciamo che i numeri primi sono finiti:
Ognuno dei fattori di questa moltiplicazione dividono
CASO 1
Se considero il numero
CASO 2
Esiste un'altra possibilità:
Sia
Allora:
Ad esempio:
Nella crittografia, vengono utilizzati numeri primi molto grandi, anche con 100 cifre decimali.
I numeri primi di 100 cifre sono circa:
Come mai abbiamo fatto la differenza tra il numero di numeri primi con 100 cifre, meno il numero di numeri primi con 99 cifre? Il motivo è che siamo interessati a contare il numero di primi che ci sono solo con 100 cifre. Per cui, abbiamo sottratto a tale risultato il numero di primi che ci sono con 99 cifre.
Come possiamo vedere, il numero di numeri primi che ci sono con 100 cifre sono
Questa frequenza può essere abbassata ancora di più sfruttando alcuni accorgimenti, tra cui:
genera M di k bit a caso // viene generato un numero di M di k bit (casuale)
for(i = 2; i * i <= M; i++){
if(M % i == 0)
goto 1 // al passo 1: "genera M di k bit a caso", M non è primo
}
return M // M è primo
C
Riprendiamo l'algoritmo precedente, per generare un numero primo di 100 cifre potrebbero essere necessari un centinaio di tentativi.
L'algoritmo in questione è molto lento.
Anzitutto viene generato un numero di
Il ciclo for parte da 2 fino ad arrivare alla radice quadrata di
Notiamo che
Il che vuol dire che
Questo vuol dire che se il numero non è primo vengono eseguiti tantissimi confronti.
Vengono eseguiti
genera M di k bit a caso // viene generato un numero di M di k bit (casuale)
for(i = 0; i < T; i++){ // si ripete T volte
genera a < M a caso
if(test(a, M)) // test(a, M) controlla che il numero a non sia divisore di M
goto 1 // al passo 1: "genera M di k bit a caso", M non è primo
}
return M // P(M non primo) < 2^(-T)
// P(M primo) > 1 - 2^(-T)
C
Con questo algoritmo la probabilità che
Supponiamo che
Il test di primalità di Miller-Rabin può dare dei falsi positivi, infatti la probabilità che
Tale test si basa su due teoremi:
Se esistono
Dimostrazione
Sia
Siccome
Presi due numeri
Conseguenza del principio fondamentale è che se
Esempio: prendiamo come numero primo
genera M di k bit a caso // viene generato un numero di M di k bit (casuale)
for(i = 0; i < T; i++){ // si ripete T volte
genera a < M a caso
if(test(a, M)) // test(a, M) controlla che il numero a non sia divisore di M
goto 1 // al passo 1: "genera M di k bit a caso", M non è primo
}
return M // P(M non primo) < 2^(-T)
// P(M primo) > 1 - 2^(-T)
C
Questa versione non cambia per niente, rispetto alla prima versione dell'algoritmo, se non fosse che il test(a, M)
che viene eseguito è il test di Miller-Rabin.
Esempio con il test di Miller-Rabin:
Probabilità che un numero sia primo con il test di Miller-Rabin:
codice
)d = 1;
for(i = k; i >= 0; i--){ // i parte dalla cifra più significativa
x = d;
d = (d * d) % M; // d = x^2 (mod M)
if(d == 1 && x != 1 && x != M - 1)
return true; // 1 = x^2 (mod M) ---(1)---
if(b^i == 1)
d = (d * a) % M;
// d = a^(M - 1) mod M = 1 ---(2)---
}
if(d != 1)
return true;
else
return false;
C
Se
La dimostrazione di questa proprietà verrà affrontata alla fine della trattazione del cifrario RSA.
Se
Ricordiamo la definizione della funzione di Eulero:
Dimostrazione:
Sia
Sia, invece
L'insieme
A questo punto:
Riscrivendo tutto:
Ora, per la proprietà III, dato che
=
Corollario Piccolo teorema di Fermat: se