MuPAD Education Group: Kostenlose Materialen für MuPAD Pro:
www.sciface.com/education, schule.mupad.de, studium.mupad.de, mupad.zum.de.

________________________________________________________________________________

 

Inhalt....: ElGamal-Algorithmus

Kategorie.: Arbeitsblatt

Mathematik: Kryptographie, Zahlentheorie

MuPAD.....: 3.0.0

Datum.....: 2003-06-23

Autoren...: Julia Faflek <faflek@mupad.de>

Funktionen: ithprime, nextprime, igcd, random, powermod,

Funktionen: numlib::toAscii, numlib::fromAscii

________________________________________________________________________________

 

Der ElGamal-Algorithmus zur Nachrichten-

verschlüsselung und zur Erstellung digitaler

Unterschriften

 

Der ElGamal-Algorithmus zur Verschlüsselung ist eine Variation des Diffie-Hellman-

Algorithmus. Dieser wird eingehend in dem Notebook "DiffieHellman.mnb", welches

unter www.schule.mupad.de/material zum Download zur Verfügung steht, untersucht.

Die Mathematik, die dem Verfahren unterliegt, ist die im wesentlichen die gleiche wie

beim Diffie-Hellman-Algorithmus. Daher wird auf weitere zahlentheoretische Hinter-

gründe im Rahmen dieses Arbeitsblattes nicht eingegangen.

 

 

Wie bei dem Diffie-Hellman-Algorithmus benötigen wir zunächst wieder

eine möglichst große Primzahl p und eine Basis g aller Elemente aus Z_p,

die ungleich 0 sind. Zur Erzeugung dieser Basis benutzen wir die Prozedur

aus dem Notebook "Diffie-Hellman.mnb". Zunächst die Prozedur, die das

Produkt der ersten n Primzahlen berechnet.

 

kleinePrim := proc(n)

begin

  _mult(ithprime(i) $ i = 1..n)

end_proc:

 

Dann die Berechnung des Produkts der entfernten Primfaktoren und des

übrig gebliebenen großen Teilers:

 

entferneFaktoren := proc(p, n)

   local grFaktor, gemFaktor, ProdFaktoren;

begin

   grFaktor := p-1:

   gemFaktor := igcd(kleinePrim(n), grFaktor):

   while (gemFaktor > 1) do

      grFaktor := grFaktor/gemFaktor:

      gemFaktor := igcd(kleinePrim(n), grFaktor):

   end_while:

   ProdFaktoren := (p-1)/grFaktor:

   return(grFaktor, ProdFaktoren):

end_proc:

 

Abschließend die Erzeugung einer Basis g:

 

Basis := proc(p, n)

   local Ergebnis, x, g, test;

begin

   Ergebnis := entferneFaktoren(p, n):

   x := random(1..p)():

   g := powermod(x, Ergebnis[2], p):

   test := powermod(g, Ergebnis[1], p):

   while (test > 1) do

      Ergebnis := entferneFaktoren(p,n):

      x := random(1..p)():

      g := powermod(x, Ergebnis[2], p):

      test := powermod(g, Ergebnis[1], p):

   end_while:

   return(g)

end_proc:

 

Wir wählen also eine zufällige große Primzahl:

 

p := nextprime(2^300)

math

und erzeugen die Basis:

 

g := Basis(p, 300)

math

Nun können wir mit der Verschlüsselung beginnen. Dazu muss jeder Teil-

nehmer seinen öffentlichen Schlüssel veröffentlichen. Als erstes wählt jede

Partei eine zufällige Zahl zwischen 1 und p-1. Dies ist der geheime

Schlüssel:

 

geheim1 := random(1..p-1)()

math

Mittels der diskreten Exponentialfunktion wird nun der öffentliche Schlüssel

berechnet:

 

oeff1 := powermod(g, geheim1, p)

math

Wir veröffentlichen unseren öffentlichen Schlüssel, damit jeder, der uns

eine Nachricht schicken möchte, weiß, mit welchen Parametern er ver-

schlüsseln muss.

 

Die Partei mit der wir kommunizieren wollen erzeugt ihre Schlüssel auf

gleiche Weise:

 

geheim2 := random(1..p-1)()

math

oeff2 := powermod(g, geheim2, p)

math

Nun können wir mit dem Ver- und Entschlüsseln beginnen. Stellen wir uns

vor, die andere Partei möchte uns folgende Nachricht zu kommen lassen:

 

Nachricht := "Hallo! Bist du auch ein MuPAD-Nutzer?".

"Kryptografie macht wirklich Spass.".

"Bin ja mal gespannt, ob du das entschluesseln kannst."

math

Nun muss der andere erst einmal aus dem Text Zahlen machen. Dazu wird

der Textstring einfach in das ASCII-Format umgewandelt:

 

Umwandlung := numlib::toAscii(Nachricht)

math

Er sucht sich unseren öffentlichen Schlüssel heraus und benutzt zusätzlich

seinen geheimen Schlüssel, um die nun vorliegende Liste von Zahlen zu

verschlüsseln. Dabei wird jede Zahl der Liste einzeln in folgender Weise

verschlüsselt:

image

 

Verschluesselung := [(Umwandlung[i] *

      powermod(oeff1, geheim2, p) mod p)

      $ i = 1..nops(Umwandlung)]:

 

Diese Verschlüsselung bekommen wir nun zugeschickt. Aber wie kommen

wir nun an den Klartext heran? Dazu müssen wir die Zahlenliste erst einmal

entschlüsseln. Wir benutzen unseren geheimen und den öffentlichen Schlüs-

sel der anderen Partei und machen die Verschlüsselung folgenderweise rück-

gängig:

image

 

Entschluesselung := [(Verschluesselung[i] *

      powermod(oeff2, p-1-geheim1, p) mod p)

      $ i = 1..nops(Verschluesselung)]

math

Das sieht doch schon aus wie eine Liste im ASCII-Format!  Wir müssen sie

lediglich noch in einen Textstring zurückwandeln:

 

numlib::fromAscii(Entschluesselung)

math

Toll! Es hat alles geklappt! Aber warum? Sei N die Klartext Nachricht, V die

Verschlüsselung und E die Entschlüsselung. Wir müssen zeigen, dass

E = N gilt. Im Weiteren gelten alle Gleichungen modulo p. Erinnern wir uns

an die Entschlüsselung:

image

Nun ersetzen wir V durch die entsprechende Verschlüsselungsvorschrift:

image

und ersetzen die öffentlichen Schlüssel durch ihre Erzeugung. Durch einige

Umformungen ergibt sich:

image

Durch Wegkürzen folgt:

image

und das ist:

image

Der kleine Fermatsche Satz besagt:

Für eine Primzahl p und alle x ungleich 0 aus Z_p gilt:

image

Damit folgt sofort:

image

Damit ist bewiesen, dass das Protokoll korrekt arbeitet.

 

Wir haben nun schon gesehen, wie der ElGamal-Algorithmus zum Ver-

schlüsseln benutzt wird. Als nächstes setzen wir die Methode von ElGamal

als Signaturverfahren ein.

 

Zunächst einiges über digitale Unterschriften:

 

Ziel der Signaturverfahren ist es, sowohl den Absender einer Nachricht ein-

deutig zu identifizieren als auch Veränderungen an einer Nachricht belegen

zu können. Denken wir nur einmal an die üblichen E-Mails. Dort kann z.B.

vor Weiterleiten einer Mail der Inhalt unbemerkt verändert werden. Ebenso

können Absenderadressen gefälscht werden. Digitale Unterschriften verhin-

dern diesen Missbrauch.

 

Die Funktionsweise einer digitalen Signatur lässt sich mit einem durchsichtigem

Safe vergleichen. Durch das Signieren wird das Dokument in den Tresor gelegt,

der dann verschlossen wird. Nur der Besitzer kann den Safe öffnen. Aber jeder

Teilnehmer kann durch den Glastresor das Dokument einsehen und verifizieren,

dass es dem Besitzer gehört.

 

Wir überlegen nun, wie wir dies mit der ElGamal-Methode umsetzen können.

Stellen wir uns vor, wir wollen die Nachricht von oben signieren. Wir behalten

alle Parameter und Schlüssel bei. Zunächst müssen wir eine zu p-1 teiler-

fremde Zahl r wählen, damit r invertierbar modulo p-1 ist:

 

r := random(1..p-1)();

while (igcd(r, p-1) > 1) do

   r := random(1..p-1)()

end_while:

r

math

math

Wir berechnen eine Zahl k mittels der diskreten Exponentialfunktion:

 

k := powermod(g, r, p)

math

Jetzt müssen wir folgende Kongruenz lösen:

image

Wir formen nach s um:

image

Nun wird klar, warum r invertierbar sein musste. Wir berechnen also zunächst

das Inverse von r:

 

invr := powermod(r, -1, p-1)

math

und berechnen s für jede Zahl in der Liste der umgewandelten Nachricht:

 

s := [0 $ nops(Umwandlung)]:

for i from 1 to nops(Umwandlung) do

   s[i] := (Umwandlung[i] - geheim1*k) * invr mod p-1

end_for:

s:

 

Die digitale Unterschrift ist das Paar (k, s). Wir schicken nun die umge-

wandelte Nachricht und die Unterschrift an die andere Partei.

Diese muss nun durch einige Rechnungen die Echtheit der Unterschrift

verifizieren. Dazu muss überprüft werden, ob folgende Gleichheit gilt:

image

Wenn dies zutrifft, kann der Andere sicher sein, dass die Unterschrift von

uns stammt. Also berechnet er:

 

Erg1 := [powermod(g, Umwandlung[i], p)

                  $ i = 1..nops(Umwandlung)]:

  

Erg2 := [(powermod(oeff1, k, p) * powermod(k, s[i], p)

                  mod p) $ i = 1..nops(s)]:

 

Nun überprüft er jeden Eintrag der Liste folgenderweise:

 

if(nops(Erg1) - nops(Erg2)=0) then

   Pruefe := [0 $ nops(Erg1)]:  

   for i from 1 to nops(Erg1) do

      Pruefe[i] := is(Erg1[i] = Erg2[i])

   end_for:

else

   error("Listen nicht gleich lang")

end_if:

Pruefe

math

 

Da alle Einträge TRUE lauten, weiß die andere Partei genau, dass auch

wirklich wir es waren, die diese Nachricht geschickt haben. Wir überlegen

noch kurz, warum das ganze funktioniert. Auch hier gelten alle Gleichungen

modulo p. Für oeff1 und k setzen wir deren Erzeugungen ein:

image

Nun folgt:

image

Wir erinnern uns an die Kongruenz:

image

Damit ergibt sich doch für eine natürliche Zahl x:

image

Jetzt können wir einsetzen

image

image

und mit dem kleinen Fermatschen Satz folgt die gewünschte Gleichheit:

image

 

 

_____________________________________________________________________________________

 

Übungen:

1. Machen Sie sich mit den Funktionen numlib::toAscii und numlib::fromAscii vertraut. Besuchen

ssSie dazu die Hilfeseiten ?numlib::toAscii und ?numlib::fromAscii.

 

2. Erzeugen Sie eine größere Primzahl, berechnen Sie die Basis und verschlüsseln Sie beliebige Textnachrichten.

_____________________________________________________________________________________

 

Anmerkungen:

 

1.  Weitere Anregungen finden Sie unter: http://schule.mupad.de bzw. http://studium.mupad.de

 

_____________________________________________________________________________________

 

 

 

MuPAD Education Group: Kostenlose Materialen für MuPAD Pro:
www.sciface.com/education, schule.mupad.de, studium.mupad.de, mupad.zum.de.