www.agora.ro

2, 3, 5, 7, 11...

Numere prime - o problemă încă nerezolvată

Valentin Gheorghiță

Securitatea datelor - principala problemă apărută în ultimii ani în cadrul rețelelor de calculatoare - se poate rezolva în mare parte prin algoritmi criptografici, care au nevoie de obicei de generatoare de numere prime foarte mari (pe 128, 256 și 512 biți), numere ce nu se găsesc în tabelele matematice. Ca urmare este nevoie să se implementeze programe de generare a numerelor prime și de testare a primalității.

Cel mai răspândit algoritm de generare a numerelor prime este Ciurul lui Eratostene, dar acest algoritm este imposibil de implementat pentru numere mari din cauza lipsei memoriei (pentru generarea numerelor prime de 128 biți ar fi necesari 2105 Mb).

Cea mai cunoscută metodă de testare a primalității unui număr natural este împărțirea lui la toate numerele naturale mai mici sau egale cu radicalul lui. Această metodă este total ineficientă din cauza timpului necesar rulării ei (pentru un număr de 128 biți sunt necesari aproximativ 4358 ani pe un calculator care efectuează 134.000.000 operații pe secundă).

Totuși problema testării primalității numerelor mari este o problemă rezolvată în mare parte de algoritmii euristici, algoritmi care determină cu o precizie foarte mare dacă un număr este prim sau nu. Înainte de a prezenta câțiva dintre acești algoritmi este necesară prezentarea unor funcții cu viteză foarte mare care implementează câteva operații matematice cu numere mari. Aceste funcții primesc ca argument numere sub formă binară, reprezentate pe n biți, cea mai nesemnificativă cifră fiind cea cu indicele 0. Numerele furnizate ca răspuns de către funcții sunt numere binare reprezentate tot pe n biți. De asemenea, funcțiile setează, dacă este nevoie, valoarea indicatorului carry (indicator care indică dacă există depășire sau nu).

Funcția sumă

Funcția realizează suma a doi operanzi primiți ca parametri. De asemenea, funcția setează indicatorul carry.

sumă(op1,op2)

carry=0

pentru i de la 0 la n-1

s[i]=op1[i]+op2[i]+carry

carry=s[i]/2

s[i]=s[i]%2

returnează s

Funcția dif

Funcția realizează diferența a doi operanzi primiți ca parametri (op1-op2).

dif(op1,op2)

d=not(op2); d=sumă(d,1); d=sumă(op1,d)

returnează d

Funcția comp

Funcția realizează compararea a doi operanzi; ea returnează:

-1 dacă op1<op2

0 dacă op1=op2

1 dacă op1>op2

comp(op1,op2)

pentru i de la n-1 la 0

dacă op1[i]>op2[i]

atunci returnează 1

altfel dacă op1[i]<op2[i]

atunci returnează -1

returnează 0

Funcția mod

Funcția realizează operația modulo prin scăderi repetate.

mod(op1,op2)

m=op1

cât timp (comp(m,op2)>=0)

execută m=dif(m,op2)

returnează m

Deoarece funcția implementează un algoritm prin scăderi repetate, este o foarte mare consumatoare de timp atunci când operanzii sunt diferiți ca ordin de mărime. În continuare vom prezenta un algoritm rapid ce rezolvă operația modulo.

fastmod(op1, op2)

dacă (comp(op1,op2)>=0) și (comp(op2,0)<>0)

atunci tmp=op2

p1=poz(op1)

p2=poz(op2)

tmp=shl(tmp,p1-p2-1)

fm=mod(op1,tmp)

dacă comp(fm,op2)>=0

atunci fm=fastmod(fm,op2)

returnează fm

Funcția poz returnează poziția celui mai semnificativ bit al argumentului.

Funcția shl(x,y) realizează deplasarea logică spre stânga a biților lui x cu y poziții.

Funcția amulb

Funcția realizează înmulțirea modulo p a doi operanzi. Funcția returnează rezultatul operației: (op1*op2)%p.

amulb(op1,op2,p)

rez=0

k=not(p);

k=sumă(k,1)

pentru i de la 0 la n-1

dacă op2(i)=1

rez=sumă(rez,op1)

cât timp carry=1

execută

rez=sumă(rez,k)

op1=shl(op1)

cât timp carry=1

execută

op1=sumă(op1,k)

cât timp comp(rez,p)>=0

execută

rez=sumă(rez,k)

returnează rez

Funcția shl realizează deplasarea logică a biților la stânga, setând indicatorul carry dacă bitul care s-a pierdut în urma deplasării avea valoarea 1.

Funcția fastexp

Funcția calculează ridicarea la putere modulo p. Funcția returnează rezultatul operației: op1op2%p

fastexp(op1,op2,p)

exp=1

cât timp compop(2,0)<>0 execută

cât timp mod(op2,2)=0 execută

op2=shr(op2)

op1=amulb(op1,op1,n)

op2=dif(op2,1)

exp=amulb(exp,op1,n)

returnează exp

Funcția cmmdc

Funcția calculează cel mai mare divizor comun a două numere naturale.

cmmdc(a,b)

dacă b=0 atunci returnează a altfel a=mod(a,b) returnează cmmdc(b,a)

În continuare vă vom prezenta trei algoritmi care testează primalitatea unui număr. Acești algoritmi au o complexitate de ordinul O(log n).

1. Testul Fermat

- se bazează pe teorema lui Euler-Fermat. Acestă teoremă spune că p este un număr prim dacă:

ap-1%p=1, pentru orice număr întreg aÎ[1,p).

Testul constă în alegerea unui a mai mic decât p și acceptarea că p este prim dacă satisface condiția de mai sus. În practică este necesară testarea doar a câtorva valori ale lui a și nu a tuturor valorilor din intervalul (1,p). Este recomandabil ca aproximativ o sută de teste să fie făcute pentru a fi convinși că numărul p ales este prim.

2. Testul Solovay-Strassen

- identifică numerele Carmichael composite. Se alege aleator un număr aÎ(1,p-1) și se testează dacă:

cmmdc(a,p)=1 și J(a,p)=a(p-1)/2%p

unde J(a,p) este operatorul Jacobi.

Dacă p este prim atunci el verifică cele două condiții, iar dacă el este composit, verificarea se face doar cu o probabilitate de 1/2. Însă efectuând k teste, probabilitatea apariției unei erori scade la 1/2k.

Operatorul Jacobi este definit în felul următor:

J(a,p)=1 dacă x2%p=a are soluție în inelul modulo p, adică a(p-1)/2%p=1

J(a,p)=-1 dacă x2%p=a nu are soluție în inelul modulo p.

Funcția care evaluează operatorul Jacobi este următoarea:

J(a,p)

dacă a=1

atunci J=1

altfel

dacă a%2=0

atunci dacă (p*p-1)/8%2=0 atunci J=J(a/2,p) altfel J=-J(a/2,p)

altfel dacă (a-1)*(p-1)/4%2=0 atunci J=J(p%a,a) altfel J=-J(p%a,a)

returnează J

Precizăm că în baza p numărul -1 este egal cu p-1.

3. Testul Rubin

Pentru ca un număr p să fie prim, el trebuie să fie un întreg impar, deci poate fi reprezentat ca:

p=2r*s+1

unde s este un întreg impar. Testul alege un număr de valori a în mod aleator din intervalul (1,p-1) și se acceptă că p este prim dacă:

sau pentru a<j<r.

În toate celelalte cazuri p nu este prim.

Valentin Gheorghiță este student în anul III la Universitatea Politehnică din București. Poate fi contactat prin e-mail la adresa:

septica@sundy.cs.ro

[cuprins]