Poiché l'operazione del modulo intero è un omomorfismo ad anello ( Wikipedia ) da ℤ -> ℤ / nℤ,
(X * Y) mod N = (X mod N) * (Y mod N) mod N
Puoi verificarlo tu stesso con un po 'di semplice algebra. (Si noti che la finale mod
sul lato destro appare a causa della definizione di moltiplicazione in un anello modulare.)
I computer usano questo trucco per calcolare gli esponenziali negli anelli modulari senza dover calcolare un gran numero di cifre.
/ 1 I = 0,
|
(X ^ I) mod N = <(X * (X ^ (I-1) mod N)) mod NI dispari,
|
\ (X ^ (I / 2) mod N) ^ 2 mod NI pari & I / = 0.
In forma algoritmica,
-- compute X^I mod N
function expmod(X, I, N)
if I is zero
return 1
elif I is odd
return (expmod(X, I-1, N) * X) mod N
else
Y <- expmod(X, I/2, N)
return (Y*Y) mod N
end if
end function
Puoi usarlo per calcolare (855^2753) mod 3233
solo con i registri a 16 bit, se lo desideri.
Tuttavia, i valori di X e N in RSA sono molto più grandi, troppo grandi per essere inseriti in un registro. Un modulo è in genere lungo 1024-4096 bit! Quindi puoi fare in modo che un computer esegua la moltiplicazione nel modo "lungo", allo stesso modo in cui facciamo la moltiplicazione a mano. Solo invece di usare le cifre 0-9, il computer utilizzerà "parole" 0-2 16 -1 o qualcosa del genere. (L'uso di soli 16 bit significa che possiamo moltiplicare due numeri a 16 bit e ottenere il risultato completo a 32 bit senza ricorrere al linguaggio assembly. Nel linguaggio assembly, di solito è molto semplice ottenere il risultato completo a 64 bit o per un computer a 64 bit , il risultato completo a 128 bit.)
-- Multiply two bigints by each other
function mul(uint16 X[N], uint16 Y[N]):
Z <- new array uint16[N*2]
for I in 1..N
-- C is the "carry"
C <- 0
-- Add Y[1..N] * X[I] to Z
for J in 1..N
T <- X[I] * Y[J] + C + Z[I + J - 1]
Z[I + J - 1] <- T & 0xffff
C <- T >> 16
end
-- Keep adding the "carry"
for J in (I+N)..(N*2)
T <- C + Z[J]
Z[J] <- T & 0xffff
C <- T >> 16
end
end
return Z
end
-- footnote: I wrote this off the top of my head
-- so, who knows what kind of errors it might have
Questo moltiplicherà X per Y per un periodo di tempo approssimativamente uguale al numero di parole in X moltiplicato per il numero di parole in Y. Questo è chiamato tempo O (N 2 ). Se guardi l'algoritmo sopra e lo selezioni, è la stessa "lunga moltiplicazione" che insegnano a scuola. Non hai tabelle dei tempi memorizzate su 10 cifre, ma puoi comunque moltiplicare 1.926.348 x 8.192.004 se ti siedi e lo risolvi.
Moltiplicazione lunga:
1,234
x 5,678
---------
9,872
86,38
740,4
6,170
---------
7,006,652
In realtà ci sono alcuni algoritmi più veloci in giro per la moltiplicazione ( Wikipedia ), come il metodo Fourier veloce di Strassen, e alcuni metodi più semplici che fanno addizione e sottrazione extra ma meno moltiplicazione, e quindi finiscono più velocemente nel complesso. Le librerie numeriche come GMP sono in grado di selezionare diversi algoritmi in base alla grandezza dei numeri: la trasformata di Fourier è solo la più veloce per i numeri più grandi, i numeri più piccoli usano algoritmi più semplici.