Parce que l'opération de module entier est un homomorphisme en anneau ( Wikipedia ) de -> / nℤ,
(X * Y) mod N = (X mod N) * (Y mod N) mod N
Vous pouvez le vérifier vous-même avec un peu d'algèbre simple. (Notez que la finale mod
à droite apparaît en raison de la définition de la multiplication dans un anneau modulaire.)
Les ordinateurs utilisent cette astuce pour calculer des exponentielles dans des anneaux modulaires sans avoir à calculer un grand nombre de chiffres.
/ 1 I = 0,
|
(X ^ I) mod N = <(X * (X ^ (I-1) mod N)) mod NI impair,
|
\ (X ^ (I / 2) mod N) ^ 2 mod NI même & I / = 0.
Sous forme algorithmique,
-- 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
Vous pouvez l'utiliser pour calculer (855^2753) mod 3233
avec des registres 16 bits uniquement, si vous le souhaitez.
Cependant, les valeurs de X et N dans RSA sont beaucoup plus grandes, trop grandes pour tenir dans un registre. Un module est généralement long de 1024 à 4096 bits! Ainsi, vous pouvez avoir un ordinateur qui fait la multiplication à la "longue" manière, de la même manière que nous effectuons la multiplication à la main. Au lieu d’utiliser les chiffres 0 à 9, l’ordinateur utilisera des "mots" 0-2 16 -1 ou quelque chose du genre. (Utiliser seulement 16 bits signifie que nous pouvons multiplier deux nombres 16 bits et obtenir le résultat complet en 32 bits sans recourir au langage assembleur. En langage assembleur, il est généralement très facile d'obtenir le résultat complet en 64 bits, ou pour un ordinateur 64 bits. , le résultat complet sur 128 bits.)
-- 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
Cela multipliera X par Y en une durée approximativement égale au nombre de mots de X multiplié par le nombre de mots de Y. On appelle cela le temps O (N 2 ). Si vous regardez l'algorithme ci-dessus et le choisissez, c'est la même "multiplication longue" qu'ils enseignent à l'école. Vous n'avez pas de tables de temps mémorisées sur 10 chiffres, mais vous pouvez toujours multiplier 1 926 348 x 8 192 004 si vous vous assoyez et que vous vous en sortez.
Longue multiplication:
1,234
x 5,678
---------
9,872
86,38
740,4
6,170
---------
7,006,652
Il existe en fait des algorithmes plus rapides pour la multiplication ( Wikipedia ), tels que la méthode de Fourier rapide de Strassen, et des méthodes plus simples qui effectuent des additions et des soustractions supplémentaires, mais moins de multiplications, et aboutissent donc plus rapidement. Les bibliothèques numériques telles que GMP sont capables de sélectionner différents algorithmes en fonction de la taille des nombres: la transformation de Fourier n'est que la plus rapide pour les plus grands nombres, les plus petits nombres utilisent des algorithmes plus simples.