16
Indagini sulla fattorizzazione RSA e sul logaritmo discreto Di Cristiano Armellini, [email protected] Fattorizzazione: metodo QR quadro Sia = con p, q numeri primi k dispari allora posso scrivere per un determinato valore di a: n-kp = 2(a+n/p) e ponendo v = n-2a ho l'equazione di II grado + = , >√ Si poteva anche considerare il caso n-kp=2(n/p-a) ma è del tutto analogo con la sola differenza che v=n+2a k pari allora posso scrivere n-kp = 2(a+n/p)+ 1 e ponendo v = n-2a-1 ho l'equazione di II grado + = , >√ Si poteva anche considerare il caso n-kp=2(n/p-a)+1 ma è del tutto analogo con la sola differenza che v=n+2a-1 Nota: se k dispari allora v dispari, se k pari allora v pari Stabilisco oltre a n anche il valore di k (k varia per ogni PC - calcolo parallelo). Il valore di k è molto importante. L'algoritmo per funzionare ha bisogno di un valore di k intero con k > p/q dove p> q ovvero k=2, 3, 4, 5, .... Negli RSA dove la dimensione di p è circa quella di q ,k può assumere un valore basso da 2 a 100 (massimo). In ogni caso k < n/8 come si può facilmente provare. Risolvo l'equazione di II grado finché non trovo le soluzioni intere facendo variare il valore del parametro v. Ecco una semplice applicazione in Python: import math; def fact(n, k): v = math.floor(math.sqrt(8*n*k)); delta = math.sqrt(math.fabs(v*v-8*n*k)); p = (v-delta)/(2*k); q = (v+delta)/(2*k); while p != math.floor(p) and q != math.floor(q): v = v+1;

Indagini sulla fattorizzazione RSA e sul logaritmo discretoarmellini.pbworks.com/w/file/fetch/79505675/Fattorizzazione e log... · VERIFICA IPOTESI DI RIEMANN i := 1 While[i

Embed Size (px)

Citation preview

Indagini sulla fattorizzazione RSA e sul logaritmo discretoDi Cristiano Armellini, [email protected]

Fattorizzazione: metodo QR quadro

Sia = con p, q numeri primi

k dispari allora posso scrivere per un determinato valore di a:

n-kp = 2(a+n/p) e ponendo v = n-2a ho l'equazione di II grado− + = , > √Si poteva anche considerare il caso n-kp=2(n/p-a) ma è del tutto analogo con la

sola differenza che v=n+2a

k pari allora posso scrivere

n-kp = 2(a+n/p)+ 1 e ponendo v = n-2a-1 ho l'equazione di II grado− + = , > √Si poteva anche considerare il caso n-kp=2(n/p-a)+1 ma è del tutto analogo con la

sola differenza che v=n+2a-1

Nota: se k dispari allora v dispari, se k pari allora v pari

Stabilisco oltre a n anche il valore di k (k varia per ogni PC - calcolo parallelo). Il

valore di k è molto importante. L'algoritmo per funzionare ha bisogno di un valore di k

intero con k > p/q dove p> q ovvero k=2, 3, 4, 5, .... Negli RSA dove la dimensione

di p è circa quella di q ,k può assumere un valore basso da 2 a 100 (massimo). In

ogni caso k < n/8 come si può facilmente provare. Risolvo l'equazione di II grado

finché non trovo le soluzioni intere facendo variare il valore del parametro v.

Ecco una semplice applicazione in Python:

import math;

def fact(n, k):

v = math.floor(math.sqrt(8*n*k));

delta = math.sqrt(math.fabs(v*v-8*n*k));

p = (v-delta)/(2*k);

q = (v+delta)/(2*k);

while p != math.floor(p) and q != math.floor(q):

v = v+1;

delta = math.sqrt(math.fabs(v*v-8*n*k));

p = (v-delta)/(2*k);

q = (v+delta)/(2*k);

if p == math.floor(p):

print(p);

print(n/p);

else:

print(q);

print(n/q);

Con semplici considerazioni algebriche si può pervenire in modo altrettanto valido

anche alle altre equazioni del tipo + + 2 = 0, − + 2 = 0, + − 2 = 0.+ + 2 = 0 .Quindi possiamo scrivere anche (dove k>p/q, p> q , k = 1, 2, 3,

4, ,.... per numeri RSA)

import math;

def fact(n, k):

v = 0;

delta = math.sqrt(math.fabs(v*v+8*n*k));

p = (v-delta)/(2*k);

q = (v+delta)/(2*k);

while p != math.floor(p) and q != math.floor(q):

v = v+1;

delta = math.sqrt(math.fabs(v*v+8*n*k));

p = (v-delta)/(2*k);

q = (v+delta)/(2*k);

if p == math.floor(p):

print(p);

print(n/p);

else:

print(q);

print(n/q);

Algoritmi per fattorizzare i numeri con il software Mathematica

Si consiglia di usare comunque l'ultima versione del software e all'occorrenza di

impostare i calcoli con un elevato numero di cifre decimali

n := 187

b := 1

a := N[Sqrt[n+b^2]]

While[a != Floor[a], b=b+1; a := N[Sqrt[n+b^2]] ]

p := a-b

q := a+b

Print[p]

Print[q]

-----------------------

n := 187

a := Floor[N[Sqrt[n]]]

b := N[Sqrt[Abs[a^2-n]]]

While[ b != Floor[b], a = a+1; b := N[Sqrt[Abs[a^2-n]]]]

p := a-b

q := a+b

Print[p]

Print[q]

-------------------------

n := 187

i := 1

p := GCD[10^i-1, n]

While[p==1, i=i+1;p := GCD[10^i-1, n] ]

Print[p]

Print[n/p]

----------------------------

Nota

Per aumentare la precisione e il numero delle cifre significative si può usare la

funzione N[], con la specifica ad esempio N[, 100] per calcoli con 100 cifre

significative

La teoria dei numeri con il software Mathematica

Di seguito esempi di codice (anche programmazione) con il software Mathematica per

applicazioni nella teoria dei numeri

FATTORIZZAZIONE CON ALGORITMO EQUAZIONE DI II GRADO

n := 2535311

s := 2*Floor[N[Sqrt[n]]]

delta := N[Sqrt[Abs[s*s-4*n]]]

While[delta != Floor[delta],s=s+2;delta := N[Sqrt[Abs[s*s-4*n]]]]

p := (s-delta)/2

q := (s+delta)/2

Print[p]

Print[q]

FATTORIZZAZIONE CON IL FATTORIALE

n := 187

s := Floor[N[Sqrt[n]]]

GCD[n, s!]

FATTORIZZAZIONE CON ATTACCO FORZA BRUTA

n := 2535311

i = 3

While[n/i != Floor[n/i],i=i+2]

Print[i]

Print[n/i]

n := 1234567891273

i := 3

While[Mod[n, i]!=0, i= i+2]

Print[i]

Print[n/i]

LISTA DEI NUMERI PRIMI

i := 1

While[i <= 100, Print[Prime[i]]; i = i+1]

Table[Prime[n], {n, 1, 100}]

TEST DI PRIMALITA'

PrimeQ[789]

FATTORIZZAZIONE

FactorInteger[187]

PHI DI EULERO

EulerPhi [67]

POTENZE MODULO N (2^34 mod 3)

PowerMod[2, 34, 3]

LOGARITMO DISCRETO (7^i = 2 mod 11)

i := 2

While[PowerMod[7, i, 11] != 2, i=i+1]

Print[i]

DIVISORI DI UN NUMERO

Divisors[86]

VERIFICA IPOTESI DI RIEMANN

i := 1

While[i<=100, Print[Zetazero[i]]; i=i+1]

For[i= 1, i < 100, i++, Print[Zetazero[i]]

Table[N[ZetaZero[i]], {i, 1, 10}] per una verifica cliccate qui (versione on line del

Mathematica)

oppure N[Table[ZetaZero[i], {i, 1, 24}]]

a livello grafico Plot[Abs[Zeta[1/2+x*I]], {x, 0, 40}] o cliccate qui

Plot[(Re[Zeta[1/2+x*I]], Im[Zeta[1/2+x*I]]), {x, 0, 40}] o cliccate qui

Algoritmi ausiliari: calcolo potenze modulo n e calcolo periodo soluzioni inDiffie-Helmann

calcolo del periodo in ≡ ( ) mod p, p primo, MCD(a, p)= 1

programma in python

import math;

def periodo(a,p):

i = 2;

while( (a**i) % p != 1 or (p-1) % i != 0):

i = i+1;

print(i);

-------------------------------------------------

calcolo potenza a^m mod n dove:

MCD(a, n) = 1

m > phi(n)

a^m nod n

programma in PARI/GP

{potenza(a, m, n) = local(c, d);

c = m % eulerphi(n);

d = (a^c) % n;

print(d);

}

Il teorema delle soluzioni del logaritmo discreto

Vedremo più in là che nel primo caso oltre ad essere intero potrebbe anche essere

un divisore di p-1 (o p-1) , mentre nel secondo caso può essere un divisore di ( ).Oltre alle soluzioni logaritmo discreto il teorema ci suggerisce un metodo per calcolare

ad esempio : ( ), ( , ) = 1Infatti se = ( ) + => = ( )Altre applicazioni: la fattorizzazione dei numeri interi (RSA) se n=pq p, q primi

s =p+q ≡ ( ), ≡ ( ), ( ), > √Trovato s (e tutti i valori in progressione aritmetica che soddisfano ≡ ( ) i

valori di p, q si trovano risolvendo l'equazione − + =Inoltre il più piccolo intero e positivo tale che ≡ 1 ( ) deve essere un divisore

di p-1 perché p-1=ke+r con 0 ≤ < => r = 0 ( ( ) ≡ 1 , ( , ) = 1)Questo prova perché le soluzioni del logaritmo discreto sotto le opportune ipotesi di

cui sopra sono tutte equidistanti ovvero in media aritmetica con ragione e dove

e | p-1. Infatti se ≡ allora y=x+be è tale che≡ ≡ , ( , ) = 1. Quindi y = x+be è soluzione di ≡ , p

primo e x soluzione data, e = ragione della progressione delle soluzioni.

Discorso analogo per l’equazione ≡ ( ) dove MCD(a, )=1, y= x+be è

soluzione con e | ( ), x è la soluzione più piccola trovata, e = ragione della

progressione delle soluzioni. Nell'equazione ≡ , con p primo (siamo qui nelle

ipotesi di Diffie-Helmann) il periodo che caratterizza tutte le soluzioni in progressione

aritmetica si calcola trovando il valore minimo tale che ≡ 1, d = periodo della

progressione aritmetica delle soluzioni. Tale valore come sopra provato deve essere

un divisore di p-1 (o molto spesso lo stesso valore p-1)

I divisori di un numero senza ripetizioni

Nel procedimento per trovare le soluzioni dell’algoritmo di Diffie-Helmann può essere

utile trovare tutti i divisori di un numero senza ripetizioni. Applicazioni: teoria dei

numeri, logaritmo discreto

import math;

def divisori(n):

j = 1;

while (j < math.floor(math.sqrt(n))):

if n % j == 0:

print(j);

print(n/j);

j = j+1;

else:

j =j+1;

le soluzioni del Logaritmo discreto e le progressioni aritmetiche

Dato il logaritmo discreto ≡ , con a, b, n noti se esiste una soluzione allora

ne esistono infinite e tutte le soluzioni sono in progressione aritmetica MCD(a, n)=1

inoltre se n è primo la ragione d | (n-1)

mentre se n=pq con p, q primi allora la ragione d | (p-1)(q-1), | ( )In alcuni casi la condizione MCD(a,n)=1 non è indispensabile, come vedremo

negli esempi seguenti

Se n=pq, con p, q primi, da ( ) = ≡ , ( ) dove

MCD(a,n)=1 ricordiamo che = , ( ), = + > √ , ≡ , ( )Questo ci aiuta nella fattorizzazione di n spendo che i fattori si trovano ,

conosciuto s risolvendo direttamente l’equazione di II grado − + =Esempio 1)

7^x = 2 mod 11

si trova che x = 3 , x = 13, x = 23, ..... (soluzioni in progressione aritmetica con

ragione 10 =11-1, 10 | 10)

Esempio 2)

7^x = 4 mod 11

si trova che x = 6 , x = 16, x = 26, ..... (soluzioni in progressione aritmetica con

ragione 10=11-1, 10 | 10)

Esempio 3)

4^x = 9 mod 11

si trova che x = 3 , x = 8, x = 13, ..... (soluzioni in progressione aritmetica con

ragione 5, 5 | 10)

Esempio 4)

2^x = 9 mod 11

si trova che x = 6 , x = 16, x = 26, ..... (soluzioni in progressione aritmetica con

ragione 10=11-1, 10 | 10)

Esempio 5)

3^x = 15 mod 17

si trova che x = 6 , x = 22, x = 38, ..... (soluzioni in progressione aritmetica con

ragione 16=17-1, 16 | 16)

Esempio 6)

204^x = 34 mod 391

si trova che x = 15 , x = 37, x = 59, ..... (soluzioni in progressione aritmetica con

ragione 22, 22 | (17-1)(23-1) = 352) qui molte in z_n.

Esempio 7)

9^x = 15 mod 33

si trova che x = 2 , x = 7, x = 12, ..... (soluzioni in progressione aritmetica con

ragione 5, 5| (3-1)(11-1)=2*10 )

Esempio 8)

3^x = 13 mod 17

si trova che x = 4 , x = 20, x = 36, ..... (soluzioni in progressione aritmetica con

ragione 16=17-1 , 16 | 16)

quindi trovando le prime due soluzioni si ha la formula per trovare tutte le altre.

Programma BC: logaritmo discreto e fattorizzazione

FATTORIZZAZIONE CON BC (BRUTE FORCE)

n = 187;

scale = 0;

p = 3;

while ( n%p != 0 )

p = p+2;

print p;

print n/p;

LOGARITMO DISCRETO CON BC (BRUTE FORCE)

i = 80;

scale = 0;

while ((204^i) % 391 != 34)

i = i+1;

print i

in Python a^x = b mod n

import math;

def logdisc(a, b, n):

i= 1;

while(a**i % n != b):

i = i+1;

print(i);

In PARI/GP

{logdisc(a, b, n) = local(i);

i = 1;

while(a^i % n != b, i=i+1);

print(i);

}

Ancora formule per problemi RSA

Dalla relazione sempre verificata + = − 2 , s=p+q, n=pq, ottengo sapendo

che q=n/p

+ (2 − ) + = 0= + √ − 42 = − √ − 42= − 2 => > 2 , > 4

V deve essere pari perché differenza di due pari

Oppure: dalle relazioni di somma e prodotto + = − 2 , =− ( − 2 ) + = 0, = ,= , > , = , >

In generale non è molto efficiente ..... Ecco un programma in Python

import math;

def facto(n):

V = 2*n;

delta = V*V-4*n*n;

p = math.sqrt((V+math.sqrt(delta))/2);

while (n%p != 0):

V = V+2;

delta = V*V-4*n*n;

p = math.sqrt((V+math.sqrt(delta))/2);

q = n/p;

print(p);

print(q);

Crivello per la fattorizzazione con le equazioni di II grado

ogni numero primo può terminare solo con una della cifre 1, 3, 7, 9

sia n = pq dove p, q sono numeri primi

In base alla seguente tabella moltiplicativa:

X 1 3 7 91 1 3 7 93 3 9 (2)1 (2)7

7 7 (2)1 (4)9 (6)3

9 9 (2)7 (6)3 (8)1

il numero n = pq con p, q primi può terminare a sua volta con una delle seguenti

cifre finali: 1, 3, 7, 9

Sia n =pq, s = p+q, d =p-q

in base quindi alla tabella abbiamo il seguente schema:

se l'ultima cifra di n = pq è:

cifra finale di n è 3 allora abbiamo le seguenti combinazioni per le cifre finali

di p, q: (3,1), (7, 9) quindi la somma s=p+q deve terminare con una delle

cifre 4, 6; mentre la differenza d=p-q con una delle cifre 2, 8

cifra finale di n è 1 allora abbiamo le seguenti combinazioni per le cifre finali

di p, q: (9,9), (1, 1), (3, 7) quindi la somma s=p+qdeve terminare con una

delle cifre 0, 2, 8; mentre la differenzad=p-q con una delle cifre 0, 4, 6

cifra finale di n è 9 allora abbiamo le seguenti combinazioni per le cifre finali

di p, q: (3,3), (1, 9), (7, 7) quindi la somma s=p+qdeve terminare con una

delle cifre 0, 4, 6; mentre la differenzad=p-q con una delle cifre 0, 2, 8

cifra finale di n è 7 allora abbiamo le seguenti combinazioni per le cifre finali

di p, q: (3,9), (7, 1) quindi la somma s=p+q deve terminare con una delle

cifre 2, 8; mentre la differenza d=p-q con una delle cifre 6, 4

Queste considerazioni ci possono essere molto utili in algoritmi di fattorizzazione del

tipo − + = 0, = + , = , = ±√ = , . Inoltre dato che − 4 deve

essere un quadrato perfetto è facile vedere che un quadrato perfetto deve terminare

con una delle cifre 0, 1, 4, 5, 6, 9. Infatti basta osservare la tabella:

I I^20 0

1 1

2 4

3 9

4 16

5 25

6 36

7 49

8 64

9 81

e questo aumenta ulteriormente la velocità nella ricerca delle soluzioni

RSA: ancora equazioni di II grado

n= pq => RSA

p-V = 2a, con V numeri dispari fissato qualsiasi

p-V = 2(q+b) =>

p-V = 2(n/p +b) => − ( + ) − =, = + 2 ± ( + 2 ) + 82

M = V+2b => M dispari (V dispari, 2b pari) => , = ±p =MCD(n, p1)

q =MCD(n, p2)

Il metodo risulta particolarmente efficiente quando p/q è circa 1/2 e in RSA

è caso abbastanza comune

import math;

def mcd(a, b):

if b == 0:

return a;

else:

return mcd(b, a%b);

def facto(n):

m = 3;

delta = m*m+8*n;

while (math.sqrt(delta) != math.floor(math.sqrt(delta))):

m = m+2;

delta = m*m+8*n;

p = (m+math.sqrt(delta))/2;

q = (m-math.sqrt(delta))/2;

a = mcd(p, n);

b = mcd(q, n);

print(a);

print(b);

Fattorizzazione biquadratica RSA

Inoltre: − + = 0, = , , = , = +, = ± √ −

e dalla relazione

= + , = , = => − − =, = ± +

> 4√ , 4|Un esempio del primo metodo in Python

import math;

def facto(n):

V = 4 * math.floor(math.sqrt(n));

s = math.sqrt(2*n + math.sqrt(V**2 +4*n**2));

while (math.floor(s) != s):

V = V+4;

s = math.sqrt(2*n + math.sqrt(V**2 +4*n**2));

x = (s+math.sqrt(s**2-4*n))/2;

y = (s-math.sqrt(s**2-4*n))/2;

print(x);

print(y);

Il teorema della periodicità dei numeri RSA

teniamo anche presente che 4 | ( ) e che in RSA deve essere ( ) > (chiave

pubblica)

Osserviamo anche che in RSA ( ) > quindi n-s+1 > e ovvero s = p+q < n+1-e .

Questo ci può aiutare sia per limitare i valori di s sia quelli di ( ) . Ecco perché e non

può essere troppo grande altrimenti e < ( ) < n-2√ +1 potrebbe essere un

intervallo piccolo per ( ) oppure 2√ < s < n+1-e potrebbe essere anche qui troppo

piccolo il range per s.

Una implementazione in Python molto semplificata e non ottimizzata è:

import math;

def mcd(a, b):

if b == 0:

return a;

else:

return mcd(b, a%b);

def facto(m):

g = 1;

h = mcd(m, 10**g-1);

while (h == 1):

g = g+1;

h = mcd(m, 10**g-1);

print(h);

print(m/h);

Fattorizzare gli RSA con la tecnica dei numeri periodici

Ecco una applicazione in Python della fattorizzazione degli RSA usando la

periodicità dei numeri

import math;

def mcd(a, b):

if b == 0:

return a;

else:

return mcd(b, a%b);

def periodo(n):

i = 1;

while ((10**i-1) % n) != 0:

i = i+1;

return i;

def facto(m):

g = periodo (m);

i = 1;

k = mcd(m, 10**i-1);

while k == 1:

if g % i != 0:

i = i+1;

else:

k = mcd(m, 10**i-1);

i = i+1;

print(k);

print(m/k);