Big Numbers¶
Note
Big numbers are supported by
GNAT Community Edition 2020
GCC 11
GCC 10 (draft, no user defined literals)
Ada 2022 introduces big integers and big real types.
Big Integers¶
The package Ada.Numerics.Big_Numbers.Big_Integers contains
a type Big_Integer and corresponding operations such as comparison
(=, <, >, <=, >=), arithmetic
(+, -, *, /, rem, mod,
abs, **), Min, Max and
Greatest_Common_Divisor. The type also has Integer_Literal
and Put_Image aspects redefined, so you can use it in a natural
manner.
Ada.Text_IO.Put_Line (Big_Integer'Image(2 ** 256));
115792089237316195423570985008687907853269984665640564039457584007913129639936
Tiny RSA implementation¶
Note
Note that you shouldn't use Big_Numbers for cryptography because it's
vulnerable to timing side-channels attacks.
We can implement the
RSA algorithm in a few lines of
code. The main operation of RSA is (md) mod n. But you can't just
write m ** d, because these are really big numbers and the result
won't fit into memory. However, if you keep intermediate result mod
n during the md calculation, it will work. Let's write this operation
as a function:
with Ada.Numerics.Big_Numbers.Big_Integers;
use Ada.Numerics.Big_Numbers.Big_Integers;
-- Calculate M ** D mod N
function Power_Mod (M, D, N : Big_Integer) return Big_Integer;
function Power_Mod (M, D, N : Big_Integer) return Big_Integer is
function Is_Odd (X : Big_Integer) return Boolean is
(X mod 2 /= 0);
Result : Big_Integer := 1;
Exp : Big_Integer := D;
Mult : Big_Integer := M mod N;
begin
while Exp /= 0 loop
-- Loop invariant is Power_Mod'Result = Result * Mult**Exp mod N
if Is_Odd (Exp) then
Result := (Result * Mult) mod N;
end if;
Mult := Mult ** 2 mod N;
Exp := Exp / 2;
end loop;
return Result;
end Power_Mod;
Let's check this with the example from Wikipedia. In that example, the public key is (n = 3233, e = 17) and the message is m = 65. The encrypted message is me mod n = 6517 mod 3233 = 2790 = c.
Ada.Text_IO.Put_Line (Power_Mod (M => 65, D => 17, N => 3233)'Image);
2790
To decrypt it with the public key (n = 3233, d = 413), we need to calculate cd mod n = 2790413 mod 3233:
Ada.Text_IO.Put_Line (Power_Mod (M => 2790, D => 413, N => 3233)'Image);
65
So 65 is the original message m. Easy!
Here is the complete code snippet:
with Ada.Text_IO;
with Ada.Numerics.Big_Numbers.Big_Integers;
use Ada.Numerics.Big_Numbers.Big_Integers;
procedure Main is
-- Calculate M ** D mod N
function Power_Mod (M, D, N : Big_Integer) return Big_Integer is
function Is_Odd (X : Big_Integer) return Boolean is
(X mod 2 /= 0);
Result : Big_Integer := 1;
Exp : Big_Integer := D;
Mult : Big_Integer := M mod N;
begin
while Exp /= 0 loop
-- Loop invariant is Power_Mod'Result = Result * Mult**Exp mod N
if Is_Odd (Exp) then
Result := (Result * Mult) mod N;
end if;
Mult := Mult ** 2 mod N;
Exp := Exp / 2;
end loop;
return Result;
end Power_Mod;
begin
Ada.Text_IO.Put_Line (Big_Integer'Image (2 ** 256));
-- Encrypt:
Ada.Text_IO.Put_Line (Power_Mod (M => 65, D => 17, N => 3233)'Image);
-- Decrypt:
Ada.Text_IO.Put_Line (Power_Mod (M => 2790, D => 413, N => 3233)'Image);
end Main;
Big Reals¶
In addition to Big_Integer, Ada 2022 provides
Big Reals.