Der euklidische Algorithmus für ganze Zahlen

Werbung
Der euklidische Algorithmus für ganze Zahlen
Ein unverzichtbares Verfahren in der Kryptographie ist der euklidische Algorithmus. In diesem Kapitel stellen wir die erste Version
für ganze Zahlen vor.
Sei im folgenden Z die Menge der ganzen Zahlen und sei der
Betrag |a| von a œ Z definiert als a für a Ø 0 und als ≠a für
a < 0.
Definition 1. Eine Zahl a œ Z teilt genau dann eine Zahl b œ Z,
wenn es eine Zahl c œ Z gibt mit ac = b. Wir nennen dann a auch
einen Teiler von b.
Grundlage für unsere weiteren Betrachtungen ist die ganzzahlige Division mit Rest.
Theorem 1. Für a, b œ Z, b ”= 0, existieren eindeutige Zahlen
r, s œ Z mit a = sb + r, wobei 0 Æ r < |b| gilt. Die Zahl s heißt
der Quotient von a durch b und r heißt der (modulare) Rest von
a durch b. Wir schreiben auch a mod b := r.
Beweis. Zunächst zeigen wir die Existenz von Quotient und Rest:
Wir setzen S := {a ≠ sb | s œ Z} fl N und wählen ein minimales
r0 := a ≠ s0 b œ S. Wir nehmen nun an, dass a ≠ s0 b = r0 Ø |b|
gilt. Falls b > 0, dann wäre r := r0 ≠ b = a ≠ (s0 + 1)b œ S, bzw.
falls b < 0, dann wäre r := r0 + b = a ≠ (s0 ≠ 1)b œ S. In beiden
Fällen hätten wir r < r0 , also einen Widerspruch zur Minimalität
von r0 . Folglich ist die Annahme falsch und es gilt r0 < |b| und
a = s0 b + r0 .
Als nächstes zeigen wir die Eindeutigkeit: Angenommen es
gibt zwei ganzzahlige Paare (s0 , r0 ) und (s1 , r1 ) mit r0 Ø r1 und
a = s0 b + r0 und b = s1 b + r1 mit 0 Æ r0 , r1 < |b|. Subtraktion
16
michael braun
der beiden Gleichungen ergibt (s0 ≠ s1 )b = r0 ≠ r1 . Folglich muss
r0 ≠ r1 Ø 0 ein Teiler von b sein. Da aber 0 Æ r0 ≠ r1 < |b|, muss
r0 ≠ r1 = 0 also r0 = r1 gelten. In diesem Fall gilt dann auch
s0 ≠ s1 = 0 und somit s0 = s1 , da b ”= 0. Insgesamt ist somit auch
die Eindeutigkeit von Quotient und Rest bewiesen.
Wir definieren nun die Menge der größten gemeinsamen Teiler
zweier ganzer Zahlen.
Definition 2. Eine Zahl t œ Z heißt genau dann ein größter
gemeinsamer Teiler von a, b œ Z, falls t ein Teiler von a und b
ist und falls jeder Teiler s œ Z von a und b die Zahl t teilt. Die
Menge der größten gemeinsamen Teiler von a und b wird mit
gcd(a, b) abgekürzt.
In dieser Definition haben wir den größten gemeinsamen Teiler
nicht als einzelne Zahl, sondern als Menge angegeben. Diese
Definition ist aber sinnvoll, da mit jedem größten gemeinsamen
Teiler t von a und b auch ≠t ein größter gemeinsamer Teiler von
a und b ist. Genaugenommen gilt t œ gcd(a, b) genau dann, wenn
gcd(a, b) = {t, ≠t} gilt. Folglich ist der größte gemeinsame Teiler
eindeutig bis auf die Menge der Einheiten Zú = {1, ≠1}. In
der Praxis beschränkt man sich bei der Definition des größten
gemeinsamen Teilers jedoch auf den normierten Wert |t| als
eindeutigen Repräsentanten.
Die Menge der größten gemeinsamen Teiler erfüllt folgende
Rechenregeln.
Lemma 1. Für a, b, s œ Z gilt:
1. gcd(a, b) = gcd(±a, ±b)
2. gcd(a, a) = aZú
3. gcd(a, 0) = aZú
4. gcd(a, 1) = Zú
5. gcd(as, bs) = s gcd(a, b)
6. gcd(b, a ≠ sb) = gcd(a, b)
7. gcd(b, a mod b) = gcd(a, b)
public-key-algorithmen
17
Ein konstruktives Verfahren, welches zu a, b œ Z einen größten
gemeinsamen Teiler berechnet, liefert der euklidische Algorithmus.
Da die Berechnung bis auf Vorzeichen eindeutig ist, können wir
uns darauf beschränken, dass a, b positiv sind und als größter
gemeinsamer Teiler eine positive Zahl bestimmt wird. Der Algorithmus basiert auf der letzten Identität von Lemma 1, welche
rekursiv angewandt wird.
Algorithmus 1. Euklidischer Algorithmus (rekursiv)
Input: a, b œ N mit a Ø b
Output: t œ gcd(a, b)
Procedure: Euklid(a, b)
1 if b = 0 then return a
2 else return Euklid(b, a mod b)
Da aufgrund von Theorem 1 a mod b < b gilt, terminiert der
Algorithmus nach endlichen vielen Schritten.
Die Idee des euklidischen Algorithmus geht dem Namen nach
bereits auf Euklid (300 v. Chr.) zurück. In seinem berühmten
Werk „Die Elemente“1 wird die Methode zur Bestimmung eines
größten gemeinsamen Teilers beschrieben, indem sukzessive die
kleinere von der größeren Zahl abgezogen wird. Die ganzzahligen
Divisionen werden also in dieser ersten Version von Euklid durch
iterierte Subtraktionen erreicht.
Eine nicht-rekursive Version ergibt sich durch die Division mit
Rest. Durch eine iterierte Division mit Rest
ri≠2 = si≠1 ri≠1 + ri
werden ausgehend von r0 = a und r1 = b mit a Ø b solange die
Reste ri mit i Ø 2 berechnet, bis rn+1 = 0 gilt. In diesem Fall
erhalten wir dann rn œ gcd(a, b).
Algorithmus 2. Euklidischer Algorithmus (iterativ)
Input: a, b œ N mit a Ø b
Output: t œ gcd(a, b)
1 v := a, u := b
2 while u ”= 0 do
3
r := v mod u /* r = v ≠ su für s = Âv/uÊ */
4
v := u, u := r
5 return v
Euklid. Die Elemente des
Euklid, Euklides: Stoicheia. http://www.operaplatonis.de/euklid/
1
18
michael braun
Um nun die Anzahl der Schritte im euklidischen Algorithmus
zu ermitteln, gehen wir vom schlechtesten Fall aus, dass bei der
ganzzahligen Division mit Rest der ganzzahlige Anteil s = 1
ist. Dies führt zur Folge der Fibonacci-Zahlen, welche durch die
Rekursion
fi = fi≠1 + fi≠2
für i Ø 2 mit den Anfangsbedingungen f0 = 0 und f1 = 1 definiert ist. Führt man den Euklidischen Algorithmus mit zwei
aufeinanderfolgenden Fibonacci-Zahlen fi+1 und fi aus, so ergibt
sich als Rest immer die nächst kleinere Fibonacci-Zahl fi≠1 , also
Âfi+1 /fi Ê = 1 und fi+1 mod fi = fi≠1 . Demnach müssen für
die Anfangswerte fn+1 und fn im Euklidischen Algorithmus n
Iterationen, d.h. n Divisionen mit Rest durchgeführt werden. Da
Ô
Ô
fn = (Fn ≠ (1 ≠ F)n ) 5, wobei F = (1 + 5)/2 ¥ 1, 62 der
Goldene Schnitt ist, erhalten wir, dass fn exponentiell wächst mit
einem ansteigenden Wert für n. Diese Worst-Case-Betrachtung
hat zur Folge, dass die Berechnung von gcd(a, b) höchstens logarithmisch für a und b ist, also linear mit der Stellenanzahl von a
und b. Diese Tatsache, dass die Anzahl der ganzzahligen Divisionen mit Rest maximal für die Fibonacci-Zahlen ist, geht auf Lamé
(1844) zurück2 .
Korollar 1. Der euklidische Algorithmus für zwei ganze Zahlen
a, b œ N mit a Ø b > 0 terminiert nach ¸ Æ logF (b) + 1 Schritten,
Ô
wobei F = (1 + 5)/2 ¥ 1, 62.
Um nun den Gesamtaufwand des euklidischen Algorithmus
zweier Zahlen a, b œ Z mit m ¥ log2 (a) ¥ log2 (b) zu bestimmen,
können wir uns überlegen, dass eine Division mit Rest einen
quadratischen Aufwand O (m2 ) besitzt. Da im schlechesten Fall
O (m) Divisionsschritte benötigt werden, kommt man daher auf
eine erste Gesamtaufwandsabschätzung von O (m3 ). Da durch die
iterierten Divisionen die Zahlen aber kleiner werden, liefert der
genaue Blick auf den Aufwand eine quadratische Komplexität. Ein
Beweis ist beispielsweise bei Shoup3 zu finden.
Theorem 2. Der euklidische Algorithmus für zwei Zahlen a, b œ N
besitzt eine Komplexität von O (log(a) log(b)).
Eine Version des euklidischen Algorithmus, welche binärer
2
T. E. Moore. Euclid’s
Algorithm and Lamé’s
Theorem on a Microcomputer. 27(4):290–295, August
1989
V. Shoup. A Computational Introduction to Number
Theory and Algebra. Cambridge University Press,
2008
3
public-key-algorithmen
euklidischer Algorithmus genannt wird, geht auf Stein4 zurück.
Laut Knuth5 wurde diese Version bereits von Silver und Tersian verwendet, aber niemals publiziert. Die Idee ist, die teuren
Divisionen durch Divisionen mit 2 und Subtraktionen zu ersetzen. Der binäre euklidische Algorithmus, auch zu Ehren seines
Erfinders steinscher Algorithmus genannt, basiert auf folgenden
Rechenregeln für den größten gemeinsamen Teiler, welche direkt
aus Lemma 1 abgeleitet werden können.
Korollar 2. Für die Menge der größten gemeinsamen Teiler von
a, b œ Z gilt:
1. gcd(a, b) = 2 gcd(a/2, b/2), falls a und b gerade.
2. gcd(a, b) = gcd(a/2, b), falls a gerade und b ungerade.
Diese beiden Regeln und Lemma 1(6) für s = 1 liefert folgenden Algorithmus.
Algorithmus 3. Steinscher Algorithmus (rekursiv)
Input: a, b œ N mit a Ø b
Output: t œ gcd(a, b)
Procedure: Stein(a, b)
1 if a = b then return a
2 if a is even then
3
if b is even then return 2 · Stein(a/2, b/2)
4
else return Stein(a/2, b)
5 else
6
if b is even then return Stein(a, b/2)
7
else return Stein(b, a ≠ b)
Bei der Anweisung 6 sind beide Zahlen a und b ungerade.
Somit ist die Zahl a ≠ b gerade und gcd(a, b) = gcd(b, a ≠ b) =
gcd(b, (a ≠ b)/2). Anstelle von Stein(b, a ≠ b) hätten wir auch
Stein(b, (a ≠ b)/2) setzen können.
Eine nicht-rekursive Version kann wie folgt formuliert werden.
Algorithmus 4. Steinscher Algorithmus (iterativ)
Input: a, b œ N mit a Ø b
Output: t œ gcd(a, b)
19
J. Stein. Computational
Problems Associated with
Racah Algebra. Journal
of Computational Physics,
1(3):397–405, 1967
5
D. E. Knuth. The Art of
Computer Programming.
Volume 2: Seminumerical
Algorithms. Addison-Wesley
Professional, 1997
4
20
michael braun
1
2
3
4
5
6
7
v := a, u := b, e := 1
while v and u are even do v := v/2, u := u/2, e := 2e
while u ”= 0 do
while v is even do v := v/2
while u is even do u := u/2
if v Ø u then v := v ≠ u else u := u ≠ v
return ev
Das folgende Lemma von Bézout besagt, dass man einen größten gemeinsamen Teiler zweier Zahlen als ganzzahlige Linearkombination der beiden Ausgangszahlen darstellen kann.
Lemma 2 (Bézout). Für ganze Zahlen a, b œ Z existieren ganze
Zahlen g, h œ Z mit ag + bh œ gcd(a, b).
Der Beweis erfolgt konstruktiv mit Hilfe des erweiterten euklidischen Algorithmus: Ohne Einschränkung der Allgemeinheit
nehmen wir a, b œ N mit a Ø b an. Wir gehen von den Gleichungen
a·1+b·0 = a
a·0+b·1 = b
aus und führen auf der rechten Seite den ersten Schritt des euklidischen Algorithmus aus, d.h. wir ziehen ein Vielfaches von b von
a ab, so dass es den Rest r = a mod b ergibt, etwa r = a ≠ s · b.
Die Erweiterung ist nun, dass wir auf der linken Seite denselben Schritt durchführen, d.h. wir ziehen das s-fache der zweiten
Gleichung von der ersten Gleichung ab und erhalten
a(1 ≠ s · 0) + b(0 ≠ s · 1) = r.
Als nächstes setzen wir den euklidischen Algorithmus für b und r
fort – sowohl für die rechte als auch für die linke Seite der Gleichungen – bis der positive größte gemeinsame Teiler von a und b
auf der rechten Seite berechnet ist. Die entsprechenden Koeffizienten für a und b auf der linken Seite sind dann die gesuchten Werte
für g und h. Allgemein starten wir mit v := a und u := b und
berechnen mit Algorithmus 4 den größten gemeinsamen Teiler,
wobei die Gleichungen
ag1 + bh1 = v
ag2 + bh2 = u
public-key-algorithmen
mit v Ø u erfüllt bleiben. Der Algorithmus terminiert, wenn u = 0.
In diesem Fall gilt dann v œ gcd(a, b) und g := g1 und h := h1
sind die gesuchten Koeffizienten mit ag + bh œ gcd(a, b).
Durch diese Modifikation von Algorithmus 4 können wir eine Variante des euklidischen Algorithmus in erweiterter Form
angeben.
Algorithmus 5. Erweiterter euklidischer Alg. (iterativ)
Input: a, b œ N mit a Ø b
Output: (t, g, h) mit ag + bh = t œ gcd(a, b)
1 g1 := 1, h1 := 0, v := a
2 g2 := 0, h2 := 1, u := b
3 while u ”= 0 do
4
s := Âv/uÊ
5
r := v ≠ su, g := g1 ≠ sg2 , h := h1 ≠ sh2
6
g1 := g2 , h1 := h2 , v := u
7
g2 := g, h2 := h, u := r
8 return (v, g1 , h1 )
Des weiteren kann der steinsche Algorithmus auch um die Berechnung der Bézout-Koeffizienten erweitert werden. Wir können
ohne Einschränkung davon ausgehen, dass nicht beide Werte a
und b gleichzeitig gerade sein können. Ansonsten können wir aufgrund von Korollar 2 (1) solange den Faktor 2 ausklammern, bis
mindestens einer der neuen Werte a oder b ungerade ist. Außerdem gilt weiterhin a Ø b. Falls dies nicht gilt, müssen die beide
Werte einfach vertauscht werden. Anschließend setzen wir mit
den Startbedinungen g1 := 1, h1 := 0, v := a und g2 := 0,
h2 := 1, u := b den steinschen Algorithmus fort, so dass zu jedem
Zeitpunkt die Invarianzen
ag1 + bh1 = v
ag2 + bh2 = u
mit |v| Ø |u| erfüllt bleiben. Falls v gerade ist und u ungerade,
dann gilt gcd(v, u) = gcd(v/2, u), d.h. wir müssen die Gleichung
ag1 + bh1 = v derart anpassen, dass hinterher v mit v/2 überschrieben wird. Dabei müssen folgende Fälle betrachtet werden.
1. Falls g1 und h1 gerade sind, so gilt
a(g1 /2) + b(h1 /2) = v/2.
21
22
michael braun
2. Falls g1 und h1 ungerade sind, so müssen a und b beide ungerade sein.
3. Falls g1 gerade und h1 ungerade sind, so muss h1 · b gerade sein
und somit auch b. Folglich ist a ungerade.
4. Falls h1 gerade und g1 ungerade sind, so muss g1 · a gerade sein
und somit auch a. Folglich ist b ungerade.
In allen drei Fällen (2),(3) und (4) sind g1 + b und h1 ≠ a gerade
und es gilt folgende Gleichung a(g1 + b) + b(h1 ≠ a) = v bzw.
a(g1 + b)/2 + b(h1 ≠ a)/2 = v/2.
Analog können wir die zweite Gleichung ag2 + bh2 = u behandeln.
Insgesamt kann der steinsche Algorithmus wie folgt erweitert
werden.
Algorithmus 6. Erweiterter steinscher Algorithmus (iterativ)
Input: a, b œ N mit a Ø b
Output: (t, g, h) mit ag + bh = t œ gcd(a, b)
1
aÕ := a, bÕ := b, e := 1
2
while aÕ and bÕ are even do aÕ := aÕ /2, bÕ := bÕ /2, e := 2e
3
g1 := 1, h1 := 0, v := a
4
g2 := 0, h2 := 1, u := b
5
while u ”= 0 do
6
while v is even do
7
v := v/2
8
if g1 and h1 are even then g1 := g1 /2, h1 := h1 /2
9
else g1 := (g1 + bÕ )/2, h1 := (h1 ≠ aÕ )/2
10
while u is even do
11
u := u/2
12
if g2 and h2 are even then g2 := g2 /2, h2 := h2 /2
13
else g2 := (g2 + bÕ )/2, h2 := (h2 ≠ aÕ )/2
14
if v Ø u then v := v ≠ u, g1 := g1 ≠ g2 , h1 := h1 ≠ h2
15
else u := u ≠ v, g2 := g2 ≠ g1 , h2 := h2 ≠ h1
16 return (ev, eg1 , eh1 )
Herunterladen