// Der Diffie-Hellman-Schlüsselaustausch ist ein Protokoll aus
// dem Bereich der Kryptografie. Mit ihm erzeugen zwei Parteien
// aus öffentlichen Zahlen einen geheimen Schlüssel.
// Bedingungen:
// Es gibt eine Zahl P, welche eine Prinmzahl sein muss,
// es gibt eine Zahl B, welche im Bereich 2 <= B <= (P - 2) liegen muss,
// Diese beiden Zahlen müssen beiden bekannt sein.
// Jede Partei erzeugt eine (bei mir mehrere) Zufallszahl(en) im Bereich
// von 1..(P - 2).
// Damit werden auf jeder Seite öffentliche Zahlen errechnet:
// Ö1 = B^Zufall1 mod P und Ö2 = B^Zufall2 mod P
// Diese Zahlen werden ebenfalls öffentlich bekannt gegeben.
// Der geheime Schlüssel errechnet sich dann jeweils:
// S1 = Ö2^Zufall1 mod P und S2 = Ö1^Zufall2 mod P
// Beispiel:
uses math;
// Partei 1 errechnet mit nachstehendem Code eine Reihe Zahlen,
// und gibt mit P, B und arrA 12 Zahlen an Partei 2 weiter.
// Die 10 Zufallszahlen (ZarrA) behält sie für sich.
var
P, B: byte;
pz: array[0..3] of byte = (7, 11, 13, 17);
arrA: array[0..9] of byte;
ZarrA: array[0..9] of byte;
procedure TForm1.Button1Click(Sender: TObject);
var x: integer;
begin
randomize;
P := pz[random(4)];
B := random(P - 3) + 2;
for x := 0 to high(arrA) do begin
ZarrA[x] := random(P - 2) + 1;
arrA[x] := round(power(B, ZarrA[x])) mod P;
end;
end;
// Partei 2 errechnet auf Grundlage von P und B
// ihrerseits Zahlen, von denen sie an Partei 1
// zehn Stück in Form von arrB zurückmeldet und
// zehn (ZarrB) für sich behält.
var
arrB: array[0..9] of byte;
ZarrB: array[0..9] of byte;
procedure TForm1.Button2Click(Sender: TObject);
var x: integer;
begin
randomize;
for x := 0 to high(arrB) do begin
ZarrB[x] := random(P - 2) + 1;
arrB[x] := round(power(B, ZarrB[x])) mod P;
end;
end;
// jetzt kann Partei 1 wieder ans Werk gehen und einen
// Wert auf Grundlage der Zahlen von Partei 2 und ihrer
// eigenen Zufallszahlen errechnen.
var
SeedA: LongInt;
procedure TForm1.Button3Click(Sender: TObject);
var x: integer;
s: string;
begin
s := '';
for x := 0 to high(arrB) do begin
s := s + inttostr(round(power(arrB[x], ZarrA[x])) mod P);
if length(s) > 7 then begin
if s[2] = '0' then setlength(s, 7) else
s := copy(s, 2, 7);
break;
end;
end;
SeedA := strtoint(s);
// Label1.caption := s;
end;
// gleichzeitig rechnet Partei 2 mit den Zahlen von Partei 1
// und ihren persönlichen Zufallszahlen einen Wert aus.
var
SeedB: LongInt;
procedure TForm1.Button4Click(Sender: TObject);
var x: integer;
s: string;
begin
s := '';
for x := 0 to high(arrA) do begin
s := s + inttostr(round(power(arrA[x], ZarrB[x])) mod P);
if length(s) > 7 then begin
if s[2] = '0' then setlength(s, 7) else
s := copy(s, 2, 7);
break;
end;
end;
SeedB := strtoint(s);
// Label2.caption := s;
end;
// Die Werte SeedA und SeedB stimmen überein: Jede Partei
// hat somit den selben Schlüssel. Und obwohl 22 Zahlen öffentlich
// hin- und hergegeben werden (können), kann man nahezu unmöglich
// den geheimen Schlüssel nachrechnen, da zum einen die 20 Zufallszahlen
// (ZarrA, ZarrB) nicht bekannt sind, und zum anderen Ziffern abgeschnitten
// werden. Der (gemeinsame) heimliche Schlüssel kann nun in weitere
// Berechnungen einbezogen werden, um damit etwas zu ver- oder entschlüsseln.