Nadesłany przez Marek Rudolf, 17 lipca 2006 01:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
diffie_hellman_d/diffie.pas:
unit diffie;
interface
uses ComObj,ActiveX;
const
MAX_PRIME_NUMBER=2147483648;
MAX_RANDOM_INTEGER=2147483648;
type
DiffieHellman=class
private
function XpowYmodN(xi,yi,ni:int64):int64;
function GeneratePrime():int64;
function IsItPrime(ni,ai:int64):boolean;
function MillerRabin(ni,trials:int64):boolean;
public
g,n,a,b,x,y,k:int64;
constructor Create();
procedure CreateKeys(var Generator,Modulus:int64);
procedure CreateSenderInterKey(var InterKey:int64);
procedure CreateRecipientInterKey(var InterKey,Generator,Modulus:int64);
procedure CreateSenderEncryptionKey(var EncryptionKey,RecipientInterKey:int64);
procedure CreateRecipientEncryptionKey(var EncryptionKey, SendersInterKey:int64);
end;
implementation
constructor DiffieHellman.Create();
begin
g := 0;
n := 0;
a := 0;
b := 0;
X := 0;
Y := 0;
K := 0;
end;
function DiffieHellman.XpowYmodN(xi,yi,ni:int64):int64;
var
tmp:int64;
begin
tmp := 0;
if (yi=1) then
result:= (xi mod Ni)
else
if ((yi and 1)=0) then
begin
tmp:= XpowYmodN(xi,yi div 2,Ni);
result:=((tmp * tmp) mod Ni);
end
else
begin
tmp := XpowYmodN(xi,(yi-1) div 2,Ni);
tmp := ((tmp * tmp) mod Ni);
tmp := ((tmp * xi) mod Ni);
result:=tmp;
end;
end;
function DiffieHellman.GeneratePrime():int64;
var
RandomNumber:TGUID;
tmp:int64;
begin
CoCreateGuid(RandomNumber);
tmp := ((RandomNumber.D1 * (RandomNumber.D2 * RandomNumber.D3)) mod MAX_PRIME_NUMBER);
//ensure it is an odd number
if ((tmp and 1)=0) then
tmp :=tmp+ 1;
if (MillerRabin(tmp,5)=true) then
begin
result:=tmp;
exit;
end;
repeat
tmp:=tmp+2;
until (MillerRabin(tmp,5)=false);
result:=tmp;
end;
function DiffieHellman.IsItPrime(ni,ai: int64):boolean;
var
d:int64;
begin
d := XpowYmodN(ai, ni-1, ni);
if (d=1) then
result:=true
else
result:=false;
end;
function DiffieHellman.MillerRabin(ni,trials:int64):boolean;
//---http://en.wikipedia.org/wiki/Miller-Rabin_test
var
i,ai:int64;
begin
ai:= 0;
i:=0;
repeat
begin
ai:= (random(ni-3))+2;// gets random value in [2..n-1]
if (IsItPrime (ni,ai)=false) then
begin
result:=false;
exit;
//n composite, return false
end;
i:=i+1;
end;
until (i>trials);
result:=true;
end;
procedure DiffieHellman.CreateKeys(var Generator,Modulus:int64);
var
swap:int64;
begin
swap:=0;
//Check if keys have already been established
if ((n<>0) and (g<>0)) then
begin
Generator := g;
Modulus := n;
end
else
begin
g := GeneratePrime();
n := GeneratePrime();
if (g>n) then
begin
swap := g;
g := n;
n := swap;
end;
Generator := g;
Modulus := n;
end;
end;
procedure DiffieHellman.CreateSenderInterKey(var InterKey:int64);
var
RandomNumber:TGUID;
begin
CoCreateGuid(RandomNumber);
a := (RandomNumber.D1 mod MAX_RANDOM_INTEGER);
X := XpowYmodN(g,a,n);
InterKey:= X;
end;
procedure DiffieHellman.CreateRecipientInterKey(var InterKey,Generator,Modulus:int64);
var
RandomNumber:TGUID;
begin
CoCreateGuid(RandomNumber);
b := (RandomNumber.D1 mod MAX_RANDOM_INTEGER);
g := Generator;
n := Modulus;
Y := XpowYmodN(g,b,n);
InterKey := Y;
end;
procedure DiffieHellman.CreateSenderEncryptionKey(var EncryptionKey,RecipientInterKey:int64);
begin
Y := RecipientInterKey;
K := XpowYmodN(Y,a,n);
EncryptionKey := K;
end;
procedure DiffieHellman.CreateRecipientEncryptionKey(var EncryptionKey, SendersInterKey:int64);
begin
X := SendersInterKey;
K := XpowYmodN(X,b,n);
EncryptionKey := K;
end;
end.

