74 lines
2.2 KiB
Plaintext
74 lines
2.2 KiB
Plaintext
COMMENT
|
|
First cut. Doesn't yet do blocking and deblocking. Also, as
|
|
encryption and decryption are identical operations but for the
|
|
reciprocal exponents used, only one has been implemented below.
|
|
|
|
A later release will address these issues.
|
|
COMMENT
|
|
|
|
BEGIN
|
|
PR precision=1000 PR
|
|
MODE LLI = LONG LONG INT; CO For brevity CO
|
|
PROC mod power = (LLI base, exponent, modulus) LLI :
|
|
BEGIN
|
|
LLI result := 1, b := base, e := exponent;
|
|
IF exponent < 0
|
|
THEN
|
|
put (stand error, (("Negative exponent", exponent, newline)))
|
|
ELSE
|
|
WHILE e > 0
|
|
DO
|
|
(ODD e | result := (result * b) MOD modulus);
|
|
e OVERAB 2; b := (b * b) MOD modulus
|
|
OD
|
|
FI;
|
|
result
|
|
END;
|
|
PROC modular inverse = (LLI a, m) LLI :
|
|
BEGIN
|
|
PROC extended gcd = (LLI x, y) []LLI :
|
|
BEGIN
|
|
LLI v := 1, a := 1, u := 0, b := 0, g := x, w := y;
|
|
WHILE w>0
|
|
DO
|
|
LLI q := g % w, t := a - q * u;
|
|
a := u; u := t;
|
|
t := b - q * v;
|
|
b := v; v := t;
|
|
t := g - q * w;
|
|
g := w; w := t
|
|
OD;
|
|
a PLUSAB (a < 0 | u | 0);
|
|
(a, b, g)
|
|
END;
|
|
[] LLI egcd = extended gcd (a, m);
|
|
(egcd[3] > 1 | 0 | egcd[1] MOD m)
|
|
END;
|
|
PROC number to string = (LLI number) STRING :
|
|
BEGIN
|
|
[] CHAR map = (blank + "ABCDEFGHIJKLMNOPQRSTUVWXYZ")[@0];
|
|
LLI local number := number;
|
|
INT length := SHORTEN SHORTEN ENTIER long long log(number) + 1;
|
|
(ODD length | length PLUSAB 1);
|
|
[length % 2] CHAR text;
|
|
FOR i FROM length % 2 BY -1 TO 1
|
|
DO
|
|
INT index = SHORTEN SHORTEN (local number MOD 100);
|
|
text[i] := (index > 26 | "?" | map[index]);
|
|
local number := local number % 100
|
|
OD;
|
|
text
|
|
END;
|
|
CO The parameters of a particular RSA cryptosystem CO
|
|
LLI p = 3490529510847650949147849619903898133417764638493387843990820577;
|
|
LLI q = 32769132993266709549961988190834461413177642967992942539798288533;
|
|
LLI n = p * q;
|
|
LLI phi n = (p-1) * (q-1);
|
|
LLI e = 9007;
|
|
LLI d = modular inverse (e, phi n);
|
|
CO A ciphertext CO
|
|
LLI cipher text = 96869613754622061477140922254355882905759991124574319874695120930816298225145708356931476622883989628013391990551829945157815154;
|
|
CO Print out the corresponding plain text CO
|
|
print (number to string (mod power (ciphertext, d, n)))
|
|
END
|