RosettaCodeData/Task/RSA-code/Delphi/rsa-code.delphi

146 lines
3.2 KiB
Plaintext

program RSA_code;
{$APPTYPE CONSOLE}
uses
System.SysUtils,
Velthuis.BigIntegers;
type
TRSA = record
private
n, e, d: BigInteger;
class function PlainTextAsNumber(data: AnsiString): BigInteger; static;
class function NumberAsPlainText(Num: BigInteger): AnsiString; static;
public
constructor Create(n, e, d: string);
function Encode(data: AnsiString): string;
function Decode(code: string): AnsiString;
end;
function EncodeRSA(data: AnsiString): string;
var
n, e, d, bb, ptn, etn, dtn: BigInteger;
begin
// a key set big enough to hold 16 bytes of plain text in
// a single block (to simplify the example) and also big enough
// to demonstrate efficiency of modular exponentiation.
n := '9516311845790656153499716760847001433441357';
e := '65537';
d := '5617843187844953170308463622230283376298685';
for var c in data do
begin
bb := ord(c);
ptn := (ptn shl 8) or bb;
end;
if BigInteger.Compare(ptn, n) >= 0 then
begin
Writeln('Plain text message too long');
exit;
end;
writeln('Plain text as a number:', ptn.ToString);
writeln(ptn.ToString);
// encode a single number
etn := BigInteger.ModPow(ptn, e, n);
Writeln('Encoded: ', etn.ToString);
// decode a single number
dtn := BigInteger.ModPow(etn, d, n);
Writeln('Decoded: ', dtn.ToString);
// convert number to text
var db: AnsiString;
var bff: BigInteger := $FF;
while dtn.BitLength > 0 do
begin
db := ansichar((dtn and bff).AsInteger) + db;
dtn := dtn shr 8;
end;
Write('Decoded number as text:"', db, '"');
end;
const
pt = 'Rosetta Code';
{ TRSA }
constructor TRSA.Create(n, e, d: string);
begin
self.n := n;
self.e := e;
self.d := d;
end;
function TRSA.Decode(code: string): AnsiString;
var
etn, dtn: BigInteger;
begin
// decode a single number
etn := code;
dtn := BigInteger.ModPow(etn, d, n);
Result := NumberAsPlainText(dtn);
end;
function TRSA.Encode(data: AnsiString): string;
var
ptn: BigInteger;
begin
ptn := PlainTextAsNumber(data);
// encode a single number
Result := BigInteger.ModPow(ptn, e, n).ToString;
end;
class function TRSA.NumberAsPlainText(Num: BigInteger): AnsiString;
var
bff: BigInteger;
begin
// convert number to text
bff := $FF;
Result := '';
while Num.BitLength > 0 do
begin
Result := ansichar((Num and bff).AsInteger) + Result;
Num := Num shr 8;
end;
end;
class function TRSA.PlainTextAsNumber(data: AnsiString): BigInteger;
var
c: AnsiChar;
bb, n: BigInteger;
begin
Result := 0;
n := '9516311845790656153499716760847001433441357';
for c in data do
begin
bb := ord(c);
Result := (Result shl 8) or bb;
end;
if BigInteger.Compare(Result, n) >= 0 then
raise Exception.Create('Plain text message too long');
end;
var
RSA: TRSA;
Encoded: string;
const
n = '9516311845790656153499716760847001433441357';
e = '65537';
d = '5617843187844953170308463622230283376298685';
TEST_WORD = 'Rosetta Code';
begin
RSA := TRSA.Create(n, e, d);
Encoded := RSA.Encode(TEST_WORD);
writeln('Plain text: ', TEST_WORD);
writeln('Encoded: ', Encoded);
writeln('Decoded: ', RSA.Decode(Encoded));
Readln;
end.