RosettaCodeData/Task/RSA-code/Icon/rsa-code.icon

66 lines
2.0 KiB
Plaintext

procedure main() # rsa demonstration
n := 9516311845790656153499716760847001433441357
e := 65537
d := 5617843187844953170308463622230283376298685
b := 2^integer(log(n,2)) # for blocking
write("RSA Demo using\n n = ",n,"\n e = ",e,"\n d = ",d,"\n b = ",b)
every m := !["Rosetta Code", "Hello Word!",
"This message is too long.", repl("x",*decode(n+1))] do {
write("\nMessage = ",image(m))
write( "Encoded = ",m := encode(m))
if m := rsa(m,e,n) then { # unblocked
write( "Encrypt = ",m)
write( "Decrypt = ",m := rsa(m,d,n))
}
else { # blocked
every put(C := [], rsa(!block(m,b),e,n))
writes("Encrypt = ") ; every writes(!C," ") ; write()
every put(P := [], rsa(!C,d,n))
writes("Decrypt = ") ; every writes(!P," ") ; write()
write("Unblocked = ",m := unblock(P,b))
}
write( "Decoded = ",image(decode(m)))
}
end
procedure mod_power(base, exponent, modulus) # fast modular exponentation
result := 1
while exponent > 0 do {
if exponent % 2 = 1 then
result := (result * base) % modulus
exponent /:= 2
base := base ^ 2 % modulus
}
return result
end
procedure rsa(text,e,n) # return rsa encryption of numerically encoded message; fail if text < n
return mod_power(text,e,text < n)
end
procedure encode(text) # numerically encode ascii text as int
every (message := 0) := ord(!text) + 256 * message
return message
end
procedure decode(message) # numerically decode int to ascii text
text := ""
while text ||:= char((0 < message) % 256) do
message /:= 256
return reverse(text)
end
procedure block(m,b) # break lg int into blocks of size b
M := []
while push(M, x := (0 < m) % b) do
m /:= b
return M
end
procedure unblock(M,b) # reassemble blocks of size b into lg int
every (m := 0) := !M + b * m
return m
end