Bởi vì hoạt động mô đun số nguyên là một phép đồng hình vòng ( Wikipedia ) từ ℤ -> / nℤ,
(X * Y) mod N = (X mod N) * (Y mod N) mod N
Bạn có thể tự xác minh điều này với một chút đại số đơn giản. (Lưu ý rằng trận chung kết mod
ở phía bên tay phải xuất hiện do định nghĩa của phép nhân trong vòng mô-đun.)
Máy tính sử dụng thủ thuật này để tính toán số mũ trong các vòng mô-đun mà không phải tính toán một số lượng lớn chữ số.
/ 1 tôi = 0,
|
(X ^ I) mod N = <(X * (X ^ (I-1) mod N)) mod NI lẻ,
|
\ (X ^ (I / 2) mod N) ^ 2 mod NI chẵn & I / = 0.
Ở dạng thuật toán,
-- 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
Bạn có thể sử dụng điều này để tính toán (855^2753) mod 3233
chỉ với các thanh ghi 16 bit, nếu bạn muốn.
Tuy nhiên, giá trị của X và N trong RSA lớn hơn nhiều, quá lớn để phù hợp với một thanh ghi. Một mô-đun thường dài 1024-4096 bit! Vì vậy, bạn có thể có một máy tính thực hiện phép nhân theo cách "dài", giống như cách chúng ta thực hiện phép nhân bằng tay. Chỉ thay vì sử dụng các chữ số 0-9, máy tính sẽ sử dụng "từ" 0-2 16 -1 hoặc đại loại như thế. (Chỉ sử dụng 16 bit có nghĩa là chúng ta có thể nhân hai số 16 bit và nhận được kết quả 32 bit đầy đủ mà không cần dùng đến ngôn ngữ lắp ráp. Trong ngôn ngữ lắp ráp, thường rất dễ dàng để có được kết quả 64 bit đầy đủ hoặc cho máy tính 64 bit , kết quả 128 bit đầy đủ.)
-- 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
Điều này sẽ nhân X với Y trong một khoảng thời gian gần bằng số lượng từ trong X nhân với số lượng từ trong Y. Đây được gọi là thời gian O (N 2 ). Nếu bạn nhìn vào thuật toán ở trên và tách nó ra, thì đó chính là "phép nhân dài" mà chúng dạy ở trường. Bạn không có số lần bảng ghi nhớ thành 10 chữ số, nhưng bạn vẫn có thể nhân 1.926.348 x 8.192.004 nếu bạn ngồi xuống và giải quyết nó.
Phép nhân dài:
1,234
x 5,678
---------
9,872
86,38
740,4
6,170
---------
7,006,652
Thực tế, có một số thuật toán nhanh hơn để nhân ( Wikipedia ), chẳng hạn như phương pháp Fourier nhanh của Strassen và một số phương pháp đơn giản hơn để thực hiện phép cộng và phép trừ nhưng nhân ít hơn và do đó kết thúc nhanh hơn. Các thư viện số như GMP có khả năng chọn các thuật toán khác nhau dựa trên mức độ lớn của các số: biến đổi Fourier chỉ nhanh nhất cho các số lớn nhất, các số nhỏ hơn sử dụng thuật toán đơn giản hơn.