146 lines
3.2 KiB
Plaintext
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.
|