¨Uber die Implementierung kryptographischer Primitive mittels

Werbung
Über die Implementierung kryptographischer
Primitive mittels sicherer
Multiagentenberechnungen
Christoph Amma
30. Januar 2007
Inhaltsverzeichnis
1 Einleitung
1.1 Grundlegenden Definitionen und Notationen . . . . . . . . . . . .
1.2 Aufbau der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . .
2
3
4
2 Kryptographische Grundlagen
2.1 Secret Sharing . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Verifiable Secret Sharing . . . . . . . . . . . . . . . . . . . . . . .
2.3 Sichere Mehrparteienberechnungen . . . . . . . . . . . . . . . . .
4
4
5
6
3 Simulation boolescher Schaltkreise
3.1 Boolesche Operatoren . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Geheime Vergleiche . . . . . . . . . . . . . . . . . . . . . . . . . .
7
7
8
4 Kontrollstrukturen und einfache Operationen
4.1 Bedingte Verzweigungen . . . . . . . . . . . . .
4.2 Schleifen . . . . . . . . . . . . . . . . . . . . . .
4.3 Berechnung nichtlinearer Funktionen . . . . . .
4.3.1 Funktionsinterpolation . . . . . . . . . .
4.3.2 Vergleiche . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
8
8
14
14
15
15
5 Langzahlarithmetik
5.1 Basisoperationen . . . . . . . . . . . . . . . . . . . . . . .
5.1.1 Division und Modulo . . . . . . . . . . . . . . . . .
5.1.2 Addition und Multiplikation von Kurzzahlen . . .
5.1.3 Geheime Vergleiche . . . . . . . . . . . . . . . . . .
5.2 Rechnen mit Langzahlen auf arithmetischen Schaltkreisen
5.2.1 Addition . . . . . . . . . . . . . . . . . . . . . . . .
5.2.2 Subtraktion . . . . . . . . . . . . . . . . . . . . . .
5.2.3 Multiplikation . . . . . . . . . . . . . . . . . . . .
5.2.4 Kurze Division mit Rest . . . . . . . . . . . . . . .
5.2.5 Verzweigungen . . . . . . . . . . . . . . . . . . . .
5.2.6 Division mit Rest . . . . . . . . . . . . . . . . . . .
5.2.7 Modulare Exponentiation . . . . . . . . . . . . . .
5.3 Binärer Fall . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4 Aufwand der Operationen . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
16
17
17
18
19
21
21
21
22
23
23
24
28
29
30
. . . . . . . . . .
30
32
6 RSA
6.1 Arithmetischer Schaltkreis über dem Ring Zpq
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
7 AES
35
8 Abschlussdiskussion
37
1
1
Einleitung
Mobile Softwareagenten sollen in den zukünftigen Rechnernetzen alltägliche
Aufgaben für ihre Besitzer übernehmen. Bei einem Agenten handelt es sich
dabei um ein autonomes Programm, welches nicht auf dem Rechner seines Besitzers ausgeführt wird. Der Agent operiert autonom im Netz und kann sich
dabei von Host zu Host bewegen (migrieren). Die Hosts führen das Programm
des Agenten aus. Der Agent wird also nicht von einem stationären Rechner aus
über das Netzwerk Serverdienste in Anspruch nehmen, sondern die Server direkt besuchen und die Dienste auf dem System selbst in Anspruch nehmen. Die
Möglichkeiten der Anwendungen reichen von der Informationsbeschaffung und
Filterung bis hin zur Recherche von günstigen Angeboten eines Produktes und
dem anschliessenden Erwerb. Damit sich dieses Konzept durchsetzen kann, muss
unabdingbar die Sicherheit eines solchen Agenten gewährleistet werden. Dieses
Problem ist bisher noch nicht befriedigend gelöst. Die Daten eines Agenten sollten im Allgemeinen geheim, die gesammelten Informationen nicht einsehbar und
das Programm des Agenten sollte unmanipulierbar sein. Die Rechner, auf denen
der Agent ausgeführt wird, sind in der Regel nicht vertrauenswürdig. Die Betreiber hätten sogar in vielen Einsatzszenarien einen Vorteil durch eine Manipulation oder Analyse der Agenten. Unter diesen Vorraussetzungen ist es schwierig,
einerseits ein Programm auf einen fremden Rechner zu migrieren, und anderseits
eine Analyse bzw. gezielte Manipulation von Code und Daten zu verhindern.
Ein Schutz vor Manipulation ist grundsätzlich unmöglich, da der ausführende
Host physikalisch uneingeschränkten Zugriff auf den Agenten haben muss. Allerdings sollte eine unbemerkte Manipulation verhindert werden. Nach einer
Manipulation sollte der Agent in einen definierten Zustand, zum Beispiel die
Terminierung, übergehen. Dies ist allerdings schwierig, da ein Agent im Allgemeinen nicht feststellen kann, ob er manipuliert wurde. Ein einzelner Agent, der
nur mit seinem Host interagiert, kann niemals sichere Berechnungen nach oben
genannten Anforderungen durchführen, was Algesheimer et.al. in [ACCK01] zeigen. Es muss also Interaktion mit mindestens einer dritten Instanz stattfinden.
Vorschläge hierfür sind entweder eine einzelne vertrauenswürdige dritte Partei
oder eine Gruppe von Agenten, die sich gegenseitig sichern. Eine einzelne universelle vertauenswürdige Instanz steht dem Konzept der Autonomie der Agenten
entgegen, da hier eine Abhängigkeit besteht, die nicht kontrollierbar ist. Bisherige Ansätze, eine sich selbst sichernde Gruppe von Agenten zu verwenden sind
entweder nicht vollständig sicher, gehen von zu starken Rahmenbedingungen aus
oder wurden nicht zu Ende gedacht. Meist wurde versucht, mittels kryprographischer Techniken, alle erdenklichen Angriffe zu verhindern. Die Problematik
dieses Ansatzes ist offensichtlich, da man im Allgemeinen nicht alle möglichen
Angriffe angeben kann.
Endsuleit und Mie verfolgen in [EM03] ebenfalls einen Ansatz, der auf Gruppen von Agenten basiert. Sie erlauben allerdings im Gegensatz zu anderen Verfahren explizit alle Arten von Angriffen. Die Agentenallianz ist so konzipiert,
dass trotz erfolgter Angriffe das korrekte Ergebnis berechnet und die Privatheit der Daten gewahrt bleibt, solange eine gewisse Schwelle korrekter und unmanipulierter Agenten nicht unterschritten wird. Endsuleit und Mie benützen
ein Verifiable Secret Sharing Scheme (VSS), um die Daten der Agenten verteilt und somit geheim zu speichern und ein darauf basierendes Protokoll für
2
sichere Mehrparteienberechnung1, um auf den Daten Berechnungen ausführen
zu können. Das Protokoll realisiert einen arithmetischen Schaltkreis über einem
endlichen Körper. Dabei können verteilte Daten lokal addiert werden, zur Multiplikation von verteilten Daten ist jedoch Kommunikation zwischen den Agenten
nötig. In dem vorgeschlagenen Modell kann eine gewisse Anzahl, hier bis zu einem Drittel, der Agenten unter feindlicher Kontrolle stehen, ohne die korrekte
Ausführung des Programms oder die Privatheit der Daten zu gefährden. Alle
Protokolle (VSS und MPC) kommen aus der Kryptographie, das heisst deren
Sicherheit kann als ausreichend analysiert bzw. sogar bewiesen gelten.
In der vorliegenden Arbeit untersuche ich die tatsächliche Praktikabilität
dieses Ansatzes. Da im Allgemeinen die Komplexität des Verfahrens für beliebige Anwendungen zu hoch ist, beschäftige ich mich mit der Analyse wichtiger
Kryptographischer Primitive, wie RSA und AES. Hierfür bestimme ich, ob und
mit welchem Aufwand sich diese Verfahren auf einem arithmetischen Schaltkreis, also letztlich auf dem vorgeschlagenen Protokoll, implementieren lassen.
Motivation ist einerseits die Notwendigkeit, daß eine Agentenallianz diese Verfahren, wie z.B. die Erstellung digitaler Signaturen, ausführen kann. Anderseits
soll an diesen Anwendungen beispielhaft untersucht werden, wie sich allgemein
formulierte Programme und Algorithmen auf einen arithmetischen Schaltkreis
transformieren lassen und damit für eine solche Agentenallianz implementieren
lassen. Ich untersuche, wie sich einfache Kontrollstrukturen, wie Schleifen und
Verzweigungen, implementieren lassen. Ausserdem gebe ich ein Verfahren zur
geheimen Berechnung beliebiger nichtlinearer Funktionen an. Dies liefert auch
eine Möglichkeit geheime Werte zu vergleichen.
Neben der Realisierbarkeit interessiert natürlich auch der Aufwand der Verfahren. Mit Aufwand ist immer der Kommunikationsaufwand gemeint, da die
Kommunikation unter den Agenten und damit das Netzwerk der beschränkende
Faktor sein wird und nicht die Rechenkapazität der ausführenden Hosts. Ich gebe weder ein allgemeines Verfahren für die Transformation, noch eine allgemeine
Abschätzung des Aufwandes an. Vielmehr werden Einzelprobleme, die sich bei
der Umsetzung der kryptographischen Verfahren ergeben, detaillierter betrachtet und gelöst. Im Besonderen wird dabei im Zuge der Umsetzung von RSA auf
dem Schaltkreis auf die Implementierung einer Langzahlarithmetik eingegangen. Die Ergebnisse liefern einen Eindruck, wie praktikabel oder unpraktikabel
der vorgeschlagene Ansatz tatsächlich ist. Man wird sehen, dass sich beide Verfahren mit vertretbarem Aufwand umsetzen lassen. Allerdings werden in beiden
Fällen Besonderheiten des jeweiligen Algorithmus ausgenutzt.
1.1
Grundlegenden Definitionen und Notationen
Ich werde nun einige wichtige Begriffe definieren. Ein durch das benutzte Secret
Sharing Scheme kodierter Wert wird im weiteren als verteilter Wert oder geheimer Wert bezeichnet. Ein nicht verteilter Wert wird als Skalar bezeichnet.
Ein arithmetischer Schaltkreis besteht nur aus Additions-, Multiplikations und Skalarmultiplikationsgattern. Ein Skalarmultiplikationsgatter multipliziert einen Skalar mit einem weiteren Skalar oder einem verteilten Wert.
Ein Multiplikationsgatter multipliziert zwei verteilte Werte. Ein Additionsgatter kann beliebige Werte addieren. Im weiteren ist mit einem arithmetischen
1 engl.
Multipartycomputation, MPC
3
Schaltkreis immer ein arithmetischer Schaltkreis über einem endlichen Körper
gemeint.
Ein arithmetischer Ausdruck ist eine direkt auf einem arithmetischen
Schaltkreis berechenbare Formel. Diese besteht nur aus mit Plus und Mal verknüpften verteilten Werten und Skalaren.
Die Multiplikationsaufwands-Funktion M(A) ist für einen arithmetischer Ausdruck A als die Anzahl der Multiplikationen verteilter Werte in dem
Ausdruck A definiert. Jede verteilte Kommunikation erfordert nach Hirt-Maurer
bei n Agenten das Senden von 2n Körperelementen pro Agent und damit 2n2
im Gesamten. Die Anzahl kommunizierter Körperelemente für einen arithmetischen Ausdruck A ist somit 2M(A)n2 . Die Kommunikationskomplexität ist die
wesentliche Größe, da die lokale Rechenkapazität der Hostst im Gegensatz zum
Kommunikationsnetz nicht der beschränkende Faktor sein wird. Die Funktion
M ist daher das entscheidende Aufwandsmaß.
1.2
Aufbau der Arbeit
Die Arbeit besteht aus sieben weiteren Abschnitten. Im nächsten führe ich die
für das Verständnis nötigen Grundlagen des secret sharing und der Mehrparteienberechnung ein. Im dritten Abschnitt gehe ich auf die Möglichkeit ein,
einen booleschen Schaltkreis mittels des gegebenen arithmetischen Schaltkreises zu simulieren und gebe damit ein erstes Verfahren an, mit dem theoretisch
jedes beliebige Programm von einer Agentenallianz ausgeführt werden kann.
Praktisch hat dieses Verfahren allerdings einen zu hohen Aufwand. Im vierten
Abschnitt behandle ich daher die Umsetzung einiger einfacher Kontrollstrukturen direkt auf einem arithmetischen Schaltkreis. Im fünften Abschnitt führe
ich eine Langzahlarithmetik auf dem Schaltkreis ein. Und in den letzten zwei
Abschnitten untersuche ich mit den erarbeiteten Lösungen die Umsetzung und
insbesondere die Komplexität von RSA und AES für eine Agentenallianz. Im letzen Abschnitt diskutiere ich die Ergebnisse hinsichtlich praktischer Bedeutung
und Anwendbarkeit auf andere Probleme.
2
2.1
Kryptographische Grundlagen
Secret Sharing
Um einen Wert geheim über mehrere Parteien verteilt zu speichern, wird ein sogenanntes Secret Sharing benutzt. Ein solches Sharing ermöglicht es, einen Wert
derart unter allen Agenten zu verteilen, dass kein einzelner Agent Informationen
über den ursprünglichen Wert erfährt. Jeder Agent erhält gewissermaßen einen
Teil der Information, ein sogenanntes share. Erst das Zusammenführen einer
festgelegten Anzahl dieser shares ermöglicht die Rekonstruktion des kodierten
Wertes. Für das vorgestellte Protokoll wird das Secret Sharing nach Shamir
[Sha79] über einem endlichen Körper verwendet. Dabei werden die Werte mithilfe von Polynomen aufgeteilt. Die Anzahl der Agenten sei mit n bezeichnet, t
sei die maximale Anzahl von Agenten, die böswillig kooperieren kann, ohne das
Geheimnis rekonstruieren zu können. Eine beliebige Teilmenge von t + 1 oder
mehr Agenten kann das Geheimnis rekonstruieren.
4
Verteilen eines Geheimnisses Ein Geheimnis wird durch ein Polynom repräsentiert, dass an der Stelle 0 den geheimen Wert annimmt. Jeder Agent erhält
einen Punkt des Polynoms. Über diese Punkte können die Agenten später das
Polynom und damit das Geheimnis rekonstruieren. Genauer erhält jeder Agent
Ai einen festen Wert αi zugewiesen, mit αi 6= αj , i, j ∈ {1, . . . , n} für i 6= j
und αi 6= 0. Dieser Wert ist die Stützstelle eines Agenten. Um ein Geheimnis s
verteilt zu speichern, wird ein zufälliges Polynom S vom Grad t und der Form
S(x) = Σti=1 ai xi + s
gewählt. Jeder Agent Ai erhält nun sein Share si mit si = S(αi ).
Rekonstruktion des Geheimnisses Eine Teilmenge von t + 1 beliebigen
Agenten kann nun mithilfe ihrer Shares das Polynom S(x) interpolieren und
damit das Geheimnis s = S(0) berechnen. Die Berechnung von S(x) kann mittels
Lagrange Interpolation erfolgen. Eine Einführung in das Interpolationsverfahren
nach Lagrange gibt beispielsweise [HH94], Kapitel 5, Abschnitt 2.1. Es sei I =
{0, . . . , k} mit #I = t + 1 eine Indexmenge für t + 1 beliebige Agenten. Es gilt
S(x) =
X
si l i
mit li =
i∈I
Y
j∈I
j6=i
αj
.
αj − αi
(1)
Das Polynom S(x) kann dadurch eindeutig berechnet werden. Eine Menge von
t oder weniger Agenten kann keinerlei Informationen über das Geheimnis gewinnen.
2.2
Verifiable Secret Sharing
Das gerade vorgestellte Secret Sharing ist nicht robust gegen Angreifer, die
Werte manipulieren. Liefert einer der t + 1 Agenten zur Rekonstruktion einen
falschen Wert, dann wird auch ein falsches Polynom interpoliert. Um den Wert
eines Geheimnisses zu rekonstruieren sind grundsätzlich t + 1 korrekte Shares
notwendig, da mit diesen das Verteilungspolynom interpoliert werden kann. Berlekamp und Welch geben in [BW86] ein Verfahren an, mit dem das Polynom
S(x) immer noch effizient berechnet werden kann, auch wenn k < (n − t)/2
Shares falsch sind. Da höchstens t Agenten manipuliert sind, gilt k ≤ t.
Das gesuchte korrekte Polynom sei mit f (x) bezeichnet. Der rekonstruierende Agent erhält von den anderen Agenten deren Shares (αi , yi ). Er berechnet
nun das Fehlerpolynom E(x), E 6= 0 vom Grad kleiner gleich k und das Polynom
B(x) := f (x) · E(x)
vom Grad kleiner gleich t + k. Es gilt somit
B(αi ) = yi · E(αi ) für i = 1, ..., n .
Falls eine Lösung für dieses lineare Gleichungssystem existiert, so liefert sie das
gesuchte Polynom f = B/E. Berlekamp und Welch zeigen, dass immer eine
Lösung existiert und diese auch eindeutig ist. Der rekonstruierende Agent muss
also das Gleichungssystem lösen, wobei der Leitkoeffizient von E auf eins gesetzt
wird um die Bedingung E 6= 0 sicherzustellen. Des weiteren ist der Wert von k
5
nicht bekannt, allerdings gilt auf jeden Fall k ≤ t. Für k wird deshalb einfach
k = t gesetzt, da dies der maximale Wert ist. Das zu lösende LGS lautet demnach
!
t−1
2t
X
X
j
el αli
für i = 1, ..., n
(2)
bj αi = yi αti ·
j=0
2.3
l=0
Sichere Mehrparteienberechnungen
Protokolle für sichere Mehrparteienberechnungen erlauben es einer Menge von
n Parteien eine bestimmte Funktion gemeinsam zu berechnen, selbst wenn bis
zu t Parteien feindlich, bzw. unter feindlicher Kontrolle sind. Dabei bleiben die
Eingaben und sämtliche Zwischenergebnisse geheim. Hirt und Maurer liefern
in [HM01] ein effizientes Protokoll, um Mehrparteienberechnungen auf einem
arithmetischen Schaltkreis über einem endlichen Körper F durchzuführen. Für
n Agenten können t < n/3 korrumpierte Agenten toleriert werden. Das heisst,
das Protokoll ist sicher und robust bis zu dieser Grenze. Es basiert auf dem oben
vorgestellten Verifiable Secret Sharing, das heisst, alle geheimen Werte werden
nach Shamir unter den Agenten verteilt gespeichert.
Rechnen mit Shares Zwei geheime Werte können lokal ohne Kommunikation
zwischen den Agenten addiert und mit einem öffentlichen Skalar, also einem
nicht verteilten Wert, multipliziert werden. Die Addition zweier Geheimnisse
g, h mit Polynomen G(x), H(x) kann einfach durch lokale Addition der Shares
berechnet werden. Dies entspricht der Addition der zwei Polynome, die durch die
Shares definiert werden. Das resultierende Polynom A(x) = G(x)+H(x) kodiert
das Ergebnis der Addition, da A(0) = G(0) + H(0) = g + h gilt. Die Multiplikation mit einem öffentlichen Skalar, also einem nicht verteilten Wert, funktioniert
analog. Die Shares werden lokal mit dem Skalar multipliziert. Auch die Multiplikation zweier Geheimnisse m = g · h funktioniert im Prinzip durch die Multiplikation der Shares, allerdings handelt es sich dabei um eine Polynommultiplikation, das heisst, die resultierenden Shares definieren ein Polynom M (x) mit
Grad 2t. Der Grad der Verteilungspolynome ist allerdings nach oben durch t beschränkt, da immer t + 1 Agenten ein Geheimnis rekonstruieren können müssen.
Um trotzdem geheime Werte multiplizieren zu können schlagen Gennaro et.al.
in [GRR98] ein entsprechendes Protokoll vor. Dieses Protokoll ermöglicht die
Multiplikation geheimer Werte bei gleichbleibenden Grad, allerdings ist dafür
Kommunikation unter den Agenten nötig, das heisst, das Ergebnis kann nicht
lokal auf den Shares berechnet werden.
Das Protokoll von Hirt-Maurer Die Addition und Multiplikation mit Skalaren werden wie oben beschrieben lokal berechnet. Für die Multiplikationsgatter
wird eine Vorberechnung durchgeführt, um die Multiplikation später zu vereinfachen. Für jedes Multiplikationsgatter wird ein Tripel (a, b, c) verteilt berechnet,
wobei a und b Zufallszahlen sind und c = a·b gilt. Die Agenten verfügen nur über
die Shares des Tripels, a, b, c sind also geheime Werte. Für die Berechnung von c
wird das oben genannte Multiplikationsverfahren von Gennaro et.al. verwendet.
Das Protokoll umfasst Teilprotokolle, um manipulierte Agenten in dieser Phase
auszuschliessen. Die eigentliche Multiplikation zweier verteilter Zahlen x, y ∈ F
6
läuft nach folgendem Verfahren ab. Das Produkt wird zu
xy
= ((x − a) + a)((y − b) + b)
= (x − a)(y − b) + (x − a)b + (y − b)a + c
umgeformt. Dabei wird eines der vorberechneten Tripel (a, b, c) verbraucht. Die
Agenten berechnen die Differenzen dx := x−a und dy := y−b und rekonstruieren
die Geheimnisse, also die tatsächlichen Werte von dx und dy . Dabei wird keine
Information über x oder y bekannt, da a und b zufällige verteilte Werte sind.
Nun kann jeder Agent lokal über die Formel
xy = dx dy + dx b + dy a + c
sein Share des Produkts berechnen. Da dx und dy bekannt sind, müssen nur noch
Skalarmultiplikationen und Additionen berechnet werden. Das Protokoll hat eine wahrscheinlich optimale Kommunikationskomplexität von O(mn2 ), wobei m
die Anzahl der Multiplikationsgatter und n die Anzahl der Agenten bezeichnet.
3
Simulation boolescher Schaltkreise
Ich betrachte nun die Problematik allgemein formulierte Programme und Algorithmen auf dem arithmetischen Schaltkreis auszuführen. In Programmen stehen Vergleiche und Kontrollstrukturen, wie Verzweigungen und Schleifen, zur
Verfügung, in dem Schaltkreis allerdings nur einfache Additions- und Multiplikationsgatter. Die Elemente der Programmiersprache müssen also durch einen
Schaltkreis ausgedrückt werden. Ein Prozessor tut genau dies mittels eines booleschen Schaltkreises. Die einfachste Methode, beliebige Programme auf einem
arithmetischen Schaltkreis auszuführen, ist demnach die Simulation eines booleschen Schaltkreises. Der Wertebereich der Variablen ist also beschränkt auf
{0, 1}. Im wesentlichen muss dann natürlich eine binäre Logik wie in einem
Prozessor implementiert werden um die Programme darauf auszuführen.
3.1
Boolesche Operatoren
Das Eins- und Nullelement des Körpers entsprechen dem Eins- und Nullelement
im boolschen Schaltkreis. Da (∧, ¬) ein vollständiges Operatorensystem bilden,
ist es ausreichend diese beiden Operatoren durch Funktionen im arithmetischen
Schaltkreis darzustellen.
boolscher Ausdruck
a∧b
¬a
arithmetische Formel
f (a, b) = a · b
f (a) = 1 − a
Dass sich diese Funktionen entsprechen, ist leicht einzusehen. In unserem Falle verteilter geheimer Werte bleiben diese auch in dem simulierten boolschen
Schaltkreis geheim. Der Operator AND benötigt eine Multiplikation und hat somit einen Kommunikationsaufwand von 2n2 , während die Negation keine Kommunikation erfordert. Weitere Operatoren, wie OR, lassen sich durch die bereits
definierten Operatoren darstellen (a ∨ b = a ∧ b). Die daraus resultierende arithmetische Formel ist a + b − ab. Der Kommunikationsaufwand des OR Operators
ist somit gleich dem des AND Operators 2n2 .
7
Die Simulation eines booleschen Schaltkreises erfordert die softwareseitige
Implementierung typischer Schaltungen in Prozessoren, wie zum Beispiel Addierer, Multiplizierer, usw., da alle Zahlen im Binärsystem vorliegen. Der Vorteil,
mit einem arithmetischen Schaltkreis beliebige Berechnungen über einem endlichen Körper beliebiger Größe auszuführen, geht verloren. Aus diesem Grund
nenne ich diesen Ansatz hier nur, um zu zeigen daß damit theoretisch alle Programme auf einem arithmetischen Schaltkreis ausführbar sind. Der Aufwand ist
allerdings praktisch sehr hoch.
3.2
Geheime Vergleiche
Für binäre Werte ist es nun einfach, Vergleichsoperatoren geheim umzusetzen,
da nur der entsprechende boolesche Ausdruck in einen arithmetischen umgewandelt werden muss. Das Ergebnis eines solchen Vergleichs ist entsprechend
der verteilte binäre Ergebniswert. Für den Gleichheits- und Größeroperator sind
die entsprechenden booleschen und arithmetischen Ausdrücke in der Tabelle angegeben.
Operator
=
>
boolescher Ausdruck
(¬a ∧ ¬b) ∨ (a ∧ b)
a ∨ ¬b
arithmetische Formel
1-a-b+ab(1+a+b-ab)
a − ab
Der Vergleich auf Gleichheit benötigt 2 Multiplikationen und hat damit einen
Kommunikationsaufwand von 4n2 . Der Größer Operator benötigt eine Multiplikation und hat einen Kommunikationsaufwand von 2n2 .
4
Kontrollstrukturen und einfache Operationen
Im folgenden Kapitel wird die Umsetzung von Kontrollstrukturen auf einen
arithmetischen Schaltkreis untersucht. Ich behandle zuerst Verzweigungen und
Schleifen als Grundbausteine von Programmen. Danach gehe ich auf Vergleiche
geheimer Werte ein. Das Grundproblem bei Verzweigungen und Schleifen ist
der mögliche Informationsverlust. So darf zum Beispiel bei einer Verzweigung
mit geheimer Bedingung aus dem Programmablauf nicht rekonstruierbar sein,
welcher Zweig tatsächlich ausgeführt wurde. Denn wäre dies nachvollziehbar,
so wäre sofort auch die Bedingung bekannt. Ähnlich besteht bei einer Schleife
mit geheimer Abbruchbedingung das Problem, dass über die Anzahl der Schleifendurchläufe die Abbruchbedingung rekonstruiert werden kann. Diese Probleme kann man lösen, indem man alle möglichen Fälle der Programmausführung
durchrechnet, allerdings nur die tatsächlich relevanten Fälle ins Ergebnis der Berechnung einbezieht. Bei Vergleichen geheimer Zahlen stellt sich das Problem,
dass die einzelnen Shares keinerlei Rückschlüsse über eine Ordnungsrelation der
geheimen Werte zulassen. Ich führe eine allgemeine Methode ein, nichtlineare
Funktionen auf einem Schaltkreis darzustellen. Da ein Vergleich von zwei geheimen Zahlen eine nichtlineare Funktion in den Wertebereich {0, 1} ist, kann man
das Problem damit lösen.
4.1
Bedingte Verzweigungen
Eine bedingte Verzweigung kann im Schaltkreis berechnet werden, allerdings
müssen immer beide Fälle der Verzweigung berechnet werden, da ansonsten die
8
Bedingung öffentlich wird. Die Bedingung b ist ein verteilter boolscher Wert,
es gilt also b ∈ {0, 1}. Die Variablen a1 und a2 seien öffentliche oder verteilte
Werte, x eine verteilte Variable. Es soll die bedingte Verzweigung
wenn b dann x ← a1 sonst x ← a2
berechnet werden. Dazu wird der dann Zweig mit dem Ergebnis der Bedingung
b, und der sonst Zweig mit 1−b, also der Negation der Bedingung, multipliziert.
Auf diese Weise wird der korrekte Zweig ausgewählt. Der arithmetische Ausdruck
hierfür lautet
x
=
ba1 + (1 − b)a2 .
Diese Form der Berechnung lässt keinerlei Rückschlüsse zu, welcher Zweig ausgewählt wurde, also welchen Wert die Bedingung b hat. Es findet also kein
Informationsverlust statt. Um die bedingte Verzweigung
wenn b dann x ← a1
zu berechnen, muss entsprechend der Ausdruck
x =
ba1 + (1 − b)x
berechnet werden. Durch den fehlenden sonst Zweig spart man keine Multiplikation. Es muss immer auch der Zweig, indem keine Veränderung der Variable
auftritt, berechnet werden, da in jedem Fall ein Wert zugewiesen werden muss.
Eine Verzweigungsoperation wird deshalb mit if bezeichnet, egal ob es sich
um eine wenn-dann oder um eine wenn-dann-sonst Verzeigung handelt. Pro
Variablenzuweisung innerhalb einer Verzweigung sind zwei Multiplikationen erforderlich. Der Multiplikationsaufwand einer bedingten Verzweigung ist also
M(if) = 2
Sei nun B der arithmetische Ausdruck, welcher die Bedingung b ergibt und
seien A1 , A2 die arithmetischen Ausdrücke, die die Werte a1 und a2 ergeben.
Der Gesamtmultiplikationsaufwand einer bedingten Verzweigung ist damit für
jede Variable, der ein Wert zugewiesen wird,
M(ifA1 ,A2 ) = M(A1 ) + M(A2 ) + 2 .
Hinzu kommt der einmalige Aufwand M(B) zur Auswertung der Bedingung.
Dieser wird nicht in die obige Formel mit einberechnet, da die Bedingung für
mehrere Variablenzuweisungen in der gleichen Verzweigung nur einmal berechnet werden muss.
Bei verschachtelten Verzweigungen muss ebenfalls jeder mögliche Fall berechnet werden. Ich betrachte beispielhaft das in Abbildung 4.1 dargestellte
Programm. Die Bedingungen Bij und die Ausdrücke Aij sind arithmetische
Ausdrücke. Man beachte, dass sie die Variable x selbst enthalten können. Aus
diesem Grund können die Ausdrücke nicht im Vorhinein ausgewertet werden, um
danach die Verzweigung zu berechnen. Ein erster Ansatz eine solche verschachtelte Verzweigung in arithmetische Ausdrücke umzuwandeln bestünde darin, die
Zuweisungen sukzessive von aussen nach innen in Ausdrücke umzuwandeln. Dabei ist die Reihenfolge der Abarbeitung wesentlich, da sich ein geänderter Wert
9
wenn B11 dann
x ← A11 ;
wenn B21 dann
x ← A21 ;
sonst
x ← A22 ;
sonst
x ← A12 ;
wenn B22 dann
x ← A23 ;
sonst
x ← A24 ;
Abbildung 1: Programm mit einer Verzweigung der Tiefe zwei mit Zuweisungen
an x in jeder Ebene und Verzweigung.
der Variable x in den Folgeausdrücken auswirken kann. Die entsprechenden Ausdrücke wären dann
b11
x
b12
b22
x
= B11
= B11 A11 + (1 − B11 )A12
= B21
= B22
= b11 (b21 A21 + (1 − b21 A22 ) + (1 − b11 )(b22 A23 + (1 − b24 )A24 )
Die Berechnung der äußeren Verzweigung ist nicht notwendig, durch Vorberechnung aller Zwischenergebnisse und korrekte Substitution dieser in die folgenden
Ausdrücke kann darauf verzichtet werden. Die entsprechenden Ausdrücke sind
dann
b11
=
B11
a11
a12
=
=
A11
A12
b21
b22
=
=
a21
a22
=
=
B21 [x ← a11 ]
B22 [x ← a12 ]
a23
a24
=
=
x =
A21 [x ← a11 ]
A22 [x ← a11 ]
A23 [x ← a12 ]
A24 [x ← a12 ]
b11 (b21 a21 + (1 − b21 )a22 ) + (1 − b11 )(b22 a23 + (1 − b22 )a24 ) ,
wobei die Substitutionen immer in eckigen Klammern hinter dem Ausdrück
angegeben sind. Auf diese Weise können alle arithmetischen Ausdrücke in einer Verzweigung vorberechnet werden. Dadurch spart man in diesem Fall zwei
Multiplikationen.
Beispiel 1. In dem Programm aus Abbildung 4.1 seien die folgende Ausdrücke
10
b11
b11
a12
b21
a21
b22
a22
b21
a24
a23
a21
a22
(b)
(a)
Abbildung 2: (a) Ein vollständiger Verzweigungsbaum der Tiefe 2. (b) Ein minimaler Verzweigungsbaum der Tiefe 2. Alle vorkommenden Ausdrücke in Zuweisungen und Bedingnungen sind schon ausgewertet und die entsprechenden Substitutionen durchgeführt. Die Ergebnisse der äusseren Zuweisungen sind nicht
dargestellt, da sie für die weitere Berechnung der Verzweigung nicht benötigt
werden.
gegeben. Die Berechnung des Vergleiches für die Bedingung B21 wird in Abschnitt vorgestellt.
A11
A21
= a+b
= x+c
A22
B21
= x−c
= x>d
Die vorberechneten und substituierten Ausdrücke lauten dann entsprechend:
a11
=
a+b
b21
a21
=
=
a22
=
a11 > d
a11 − c
a11 + c
Eine vollständige Verzweigung der Tiefe 2 benötigt also 6 Multiplikationen,
zuzüglich des Aufwandes für die Berechnung der Ausdrücke in den Zuweisungen
und der Bedingungen. Vollständig bedeutet, dass bis zu einer gegebenen Tiefe
jeder Ausdruck wieder eine Verzweigung ist.
Für verschachtelte Verzweigungen beliebiger Tiefe funktioniert das Verfahren
analog. Die Ausdrücke werden sukzessive in die innerste Verzweigung substituiert und dann der enstprechende Ausdruck für die Verzweigung berechnet.
Allgemein lässt sich eine solche geschachtelte Verzweigung als Binärbaum
darstellen. Ein Knoten entspricht der Bedingungen einer Verzweigung, die linke
Kante eines Knotens entspricht dem dann Zweig, die rechte dem sonst Zweig.
Die Kanten werden mit den Ergebnissen der arithmetischen Ausdrücken, die
in der Verzweigung zu berechnen sind, markiert. Die Blätter des Baumes sind
unmarkiert und können ignoriert werden. Abbildung 2(a) zeigt einen solchen
Baum der Tiefe 2 für eine vollständige Verzweigung. Der Baum ist in diesem
11
Fall ebenfalls vollständig. Ein minimaler Baum einer gegebenen Tiefe hat in jeder Verschachtelungstiefe nur eine Verzweigung, Abbildung 2(b) zeigt den entsprechenden minimalen Baum für die Tiefe 2. Der entsprechende arithmetische
Ausdruck für diesen Baum ist
b11 (b21 a21 + (1 − b21 )a22 ) + (1 − b11 )a12 .
Es sind also vier Multiplikationen nötig. Ich bestimme die Anzahl der Multiplikationen für diese beiden Fälle in Abhängigkeit der Verschachtelungstiefe, um
eine obere und untere Schranke des Aufwandes für eine Verzweigung zu erhalten.
T (x) bezeichne im weiteren die Anzahl der Multiplikationen für die Verzweigung
in Abhängigkeit der Tiefe x, ohne die Auswertung der arithmetischen Ausdrücke
für die Bedingungen und Zuweisungen.
Ich betrachte zuerst den Fall der vollständigen Verzweigung. Anhand des
Baumes lässt sich leicht sehen, dass für die nächste Verzweigungstiefe die Anzahl der Verzweigungen verdoppelt wird und noch eine weitere Verzweigung
hinzukommt. Anschaulich wird der bisherige Baum dupliziert und die beiden
Bäume über eine Verzweigung verbunden. Die entsprechende Rekurrenzrelation
ist demnach
T (1) =
T (n + 1) =
2
2T (n) + 2
Satz 2. Eine Zuweisung innerhalb einer vollständig verschachtelten Verzweigung der Tiefe n benötigt T (n) = 2n+1 − 2 Multiplikationen.
Beweis. Der Beweis erfolgt induktiv. Sei n die Tiefe der Verzweigung, dann gilt
für n = 1
T (1) = 22 − 2 = 2 .
Die Rekurrenzrelation lautet
T (n + 1) = 2T (n) + 2 .
Es gelte die Induktionsannahme T (n) = 2n+1 − 2 für ein n ∈ N. Damit ergibt
sich für n → n + 1
T (n + 1) = 2T (n) + 2 = 2(2n+1 − 2) + 2 = 2 · 2n+1 − 4 + 2 = 2n+2 − 2 .
Für den minimalen Aufwand einer verschachtelten Verzweigung gilt die Rekurrenzrelation
T (1) =
T (n + 1) =
2
T (n) + 2 ,
da für eine um eins höhere Verzweigungstiefe genau eine Verzweigung hinzu
kommt.
Satz 3. Eine Zuweisung innerhalb einer minimal verschachtelten Verzweigung
der Tiefe n benötigt T (n) = 2n Multiplikationen.
12
Beweis. Der Beweis erfolgt ebenfalls induktiv. Sei n die Tiefe der Verzweigung,
dann gilt für n = 1
T (1) = 2 · 1 = 2 .
Die Rekurrenzrelation lautet
T (n + 1) = T (n) + 2 .
Es gelte die Annahme T (n) = 2n für ein n ∈ N, damit ergibt sich für n → n + 1
T (n + 1) = T (n) + 2 = 2n + 2 = 2(n + 1) .
Satz 2 und Satz 3 liefern obere und untere Schranken für den Multiplikationsaufwand T (n) einer Verzweigung der Tiefe n. Für eine Verzweigung der
Tiefe n gilt also
2n ≤ T (n) ≤ 2n+1 − 2
(3)
Beispiel 4. Ich betrachte als Beispiel eine verschachtelte Verzweigung aus Algorithmus 6 (Seite 26) Zeilen 9 bis 13. Das Programm hat die Form:
wenn b1 dann
q ← q − 1;
c ← c + v;
wenn b2 dann
q ← q − 1;
Zuerst werden die Ausdrücke in der äußeren Verzweigung in die innere Verzweigung substituiert. Zu beachten ist, dass auch in dem im Programm fehlenden sonst Fall substituiert werden muss. Die Zuweisung an c bleibt stehen, da
die Variable in der inneren Verzweigung nicht mehr vorkommt. Bezüglich der
Variable c handelt es sich hier nur um eine Verzweigung der Tiefe 1. Nach der
Substitution hat das Programm die Form:
wenn b1 dann
c ← c + v;
wenn b2 dann
q ← q − 2;
sonst
q ← q − 1;
sonst
c ← c;
Nun kann für die Berechnung von q und c ein arithmetischer Ausdruck angegeben werden. Die Ausdrücke lauten:
q
=
c
=
b1 (b2 (q − 2) + (1 − b2 )(q − 1)) + (1 − b1 )q
b1 (c + v) + (1 − b1 )c
Es werden also insgesamt 6 Multiplikationen benötigt.
13
4.2
Schleifen
Bei Schleifen mit geheimen Abbruchbedingungen stellt sich das gleiche Problem
wie bei den Verzweigungen. Es müssen alle möglichen Fälle, also Durchläufe,
berechnet werden. Würde die Schleife gemäß der Abbruchbedingung beendet,
käme es zu einem Informationsverlust. Ein potentieller Angreifer könnte die
Anzahl der Durchläufe bestimmen und damit Rückschlüsse über die in der Abbruchbedingung vorkommenden Variablen ziehen. Das folgende Beispiel demonstriert dies.
Beispiel 5. Ich betrachte die Schleife mit der geheimen Variablen x und y.
solange x > c tue
y ←y+d
x←x−e
Bricht die Schleife tatsächlich ab, wenn die Bedingung x ≤ c eintritt, ist die
Anzahl der Durchläufe D bekannt. Man weiss damit, dass der Wert von y nach
Ausführung der Schleife ynach = yvor +D ·d ist. Wäre die Anzahl der Durchläufe
der Schleife nicht bekannt, dann kennt man den Wert von y nach Ausführung der
Schleife nicht, selbst wenn dieser vor Ausführung der Schleife bekannt war. Auch
über den Wert von x bekommt man Informationen, falls die Schleife abbricht. In
diesem Fall ist die Differenz zwischen x vor der Schleife und c bekannt und man
weiss dass nach der Schleife xnach = xvor − e · D gilt. Dass nach der Schleife
x ≤ c gilt, ist immer bekannt, auch wenn die Anzahl der Durchläufe geheim
bleibt.
Eine Schleife mit geheimer Abbruchbedingung kann im Schaltkreis dargestellt werden. Die Schleife wird in diesem Fall maximal oft ausgeführt und über
Multiplikation mit der Bedingung und deren Komplement werden die ungewollten Durchläufe wieder ausgeblendet. Eine Schleife der Form
solange B tue
x ← A1
deren maximale Anzahl an Iterationen k betrage, kann in die Ausdruckssequenz
x =
x =
..
.
x =
b1 A1 + (1 − b1 )x,
b2 A2 + (1 − b2 )x,
bk Ak + (1 − bk )x
umgewandelt werden. Die Variable bi bezeichne dabei das Ergebnis der Auswertung von B in der i-ten Iteration. Dies entspricht k bedingten Verzweigungen
oder einer minimalen verschachtelten Verzweigung der Tiefe k. Der Multiplikationsaufwand beträgt 2k Multiplikationen.
4.3
Berechnung nichtlinearer Funktionen
Da ein arithmetischer Schaltkreis nur über Additions- und Multiplikationsgatter
verfügt, lassen sich damit nur lineare Funktionen direkt darstellen. Man will
14
natürlich aber auch nichtlineare Funktionen berechnen können. Ich betrachte
eine beliebige n-stellige Funktion der Form
f : Fn → F,
(x1 , . . . , xn ) → y
Für die von mir betrachteten Verfahren genügt die Beschränkung des Wertebereichs auf eine Dimension. Grundsätzlich ist aber auch ein mehrdimensionaler Wertebereich kein Problem. Da F ein endlicher Körper ist, ist auch der
Definitions- und Wertebereich der Funktion f endlich. Genauer hat der Definitionsbereich die Größe |F|n und der Wertebereich die Größe |F|. Es gibt also
genau |F|n Wertepaare, die die Funktion vollständig definieren. Diese Wertepaare definieren auf eindeutige Weise ein Polynom P vom Gesamtgrad |F|n − 1. Da
es sich bei dem Polynom P um eine lineare Abbildung handelt kann es direkt
im Schaltkreis berechnet werden. Damit läßt sich also prinzipiell jede beliebige
Funktion berechnen.
4.3.1
Funktionsinterpolation
Ich stelle das Verfahren der Berechnung von nichtlinearen Funktionen mittels
interpolierter Polynome detaillierter dar und bestimme den Multiplikationsaufwand einer solchen Berechnung. Dabei beschränke ich mich auf den Fall einstelliger Funktionen, also Funktionen der Form f : F → F, da nur diese in der
weiteren Arbeit benötigt werden. Ich betrachte also eine beliebige Funktion
f : F → F,
f (x) = y .
Die Funktion ist bekannt und damit auch alle Werte, die sie annimmt. Man
kennt also die Paare (x, f (x)) für alle x ∈ F. Diese definieren ein Polynom p
vom Grad d = |F| − 1 mit der Eigenschaft
p(x) = f (x), ∀x ∈ F .
Das Polynom hat die Form
p(x) = αd xd + αd−1 xd−1 + . . . + α1 x + α0 ,
αi ∈ F.
Der Koeffizientenvektor (αd , αd−1 , . . . , α0 ) ist öffentlich und jedem Agenten bekannt. Damit können die Agenten die Funktion f gemeinsam berechnen, es muss
lediglich das Polynom an der entsprechenden Stelle ausgewertet werden. Geheime Multiplikationen sind nur für die Berechnung der Potenzen von x notwendig.
Die jeweils nächsthöhere Potenz kann aus der vorhergehende durch eine Multiplikation gemäß xk+1 = xk · x für alle x ∈ N berechnet werden. Insgesamt sind
demnach d − 1 = |F| − 2 verteilte Mulitplikationen nötig.
4.3.2
Vergleiche
Vergleiche geheimer Werte sind nicht einfach zu realisieren. Die Shares der einzelnen Agenten stehen bezüglich einer Ordnungsrelation in keinem Zusammenhang zu den tatsächlichen geheimen Werten. Ein Vergleich auf Gleichheit kann
allerdings auf die Berechnung des multiplikativ Inversen eines Körperelements
zurückgeführt werden. Es gilt
x · x−1 = 1 , x ∈ F/{0} .
15
Ich definiere nun eine Funktion inv zur Berechnung des Inversen, die auch für
die 0 definiert ist
−1
x
falls x 6= 0
inv(x) =
0
sonst
Damit kann nun eine Funktion eq mit
eq(a, b) = 1 − ((a − b) · inv(a − b))
zum Vergleich zweier Zahlen angegeben werden, denn es gilt
1 falls a = b
eq(a, b) =
0
sonst
Die Berechnung der Funktion inv kann gemäß dem Verfahren in Abschnitt
4.3.1 durch ein interpolierendes Polynom berechnet werden. Damit ergibt sich
ein Multiplikationsaufwand für die Gleichheitsfunktion von
M(eq) = M(inv) + 1 = |F| − 1 .
Ein Vergleich auf Ungleichheit kann einfach durch Negierung des Ergebnisses
der Gleichheitsfunktion erfolgen. Die Negation wurde bereits in Abschnitt 3.1
vorgestellt, ich führe sie hier noch einmal unter dem Bezeichner
not(x) = 1 − x ,
x ∈ {0, 1}
ein. Der Ungleichheitsoperator neq(x, y) kann dann als
neq(a, b) = not(eq(a, b))
dargestellt werden. Es gilt
M(neq) = M(eq) = |F| − 1
Ob eine Zahl grösser oder kleiner als eine andere ist, läßt sich nicht ohne weiteres feststellen, da ein endlicher Körper keine Ordnung hat. Eine Möglichkeit ist
natürlich auch hier wieder die Interpolation durch ein Polynom. In diesem Fall
muss allerdings eine Funktion in zwei Variablen interpoliert werden, was auch
zu einem Interpolationspolynom in zwei Variablen führt. Unter Umständen gibt
es aber noch effizientere Verfahren. Ich werde in Abschnitt 5.1.3 in Zusammenhang mit der Einführung einer Langzahlarithmetik eine effizientere Möglichkeit
vorstellen, die aber nicht im Allgemeinen funktioniert. Da sie für die Betrachtungen in dieser Arbeit aber ausreicht, werde ich das allgemeine Verfahren nicht
genauer analysieren.
5
Langzahlarithmetik
Da für Primitive der Public-Key Kryptographie große Zahlen benötigt werden
soll im Folgenden eine Langzahlarithmetik auf dem arithmetischen Schaltkreis
über dem Körper F aufgebaut werden. Ich nehme für F einen Primkörper der
Ordnung p an. Eine LangzahlP
a wird wie üblich bezüglich einer Basis B dargen−1
stellt und hat die Form a = i=0
ai B i , n ist die Stelligkeit. Die größte noch
darstellbare Zahl im Körper muss B 2 − 1 sein. Dieser Wert ist momentan noch
16
nicht direkt nachvollziehbar, damit wird aber sichergestellt, dass bei den für die
Langzahlarithmetik nötigen Verknüfungen von Zahlen nie eine Reduktion modulo p im Körper F kommt. Damit soll eine Einbettung in die ganzen Zahlen
simuliert werden. Es ergibt sich der Zusammenhang
p
B 2 − 1 < p ⇔ B 2 < p + 1 ⇔ B < ⌊ p + 1⌋
√
Die größtmögliche Basis im Körper Fp ist somit B = ⌊ p + 1⌋. Wir betten also
ein Stellenwertsystem zur Basis B in unseren Körper F ein. Die Menge
B := {0, .., B − 1}
beinhaltet die möglichen Werte einer Ziffer in einer Langzahl. Eine einstellige
Zahl wird auch als Kurzzahl bezeichnet.
Die nachfolgenden Algorithmen und ihr jeweiliger Aufwand Aufwände gelten nur für B ≥ 3. Auf den Spezialfall B = 2 gehe ich in Abschnitt 5.3 genauer ein, da dieser Fall auch einfachere Algorithmen für die Langzahlarithmetik
ermöglicht.
5.1
Basisoperationen
Um eine Langzahlarithmetik auf einem arithmetischen Schaltkreis zu implementieren sind folgende Operationen notwendig:
1. Die Division mit Rest von Kurzzahlen. Für gegebende a, b ∈ B soll q, r ∈ B
mit a = b·q +r berechenbar sein. Das entspricht den Operatoren a div b =
⌊a/b⌋ und a mod b = a mod b.
2. Addition und Multiplikation zweier Kurzzahlen mit Übertrag.
3. Vergleich zweier Kurzzahlen auf Gleichheit, Grösser und Kleiner.
4. Die Division einer zweistelligen Zahl durch eine einstellige Zahl für den
Fall, dass das Ergebnis, also der Quotient, wieder einstellig ist. Also q =
⌊(a1 · B + a0 )/b⌋ mit a0 , a1 , b ∈ B und der Vorraussetzung, dass auch q ∈ B
gilt. Diese Operation wird für die Implementierung einer Langzahldivision
benötigt.
Ich führe nun verschiedene Operationen ein, deren Notation einem einheitlichen
Schema folgt. Alle Operationen werden in Proportionalschrift dargestellt (z.B.
op). Die Anzahl der Argumente, die aus verteilten Werten bestehen können,
wird als Zahl hinter der Operation angeben (z.B. op1 oder op2). Hat die Anzahl
geheimer Argumente keinen Einfluss auf den Aufwand wird die Zahl weggelassen
(z.B. op). Handelt es sich um eine Operation, deren Argumente aus Langzahlen
bestehen, wird zusätzlich der Buchstabe l vorangestellt (z.B. lop1).
5.1.1
Division und Modulo
Ich untersuche den Aufwand für die div und mod Operationen in verschieden
Varianten. Die Funktionen div1 und mod1 bezeichnen die Division und Reduktion im Falle, dass nur ein Operand geheim ist und der andere feststeht. Für die
Langzahlarithmetik ist der Divisor auf B festgesetzt. Es gilt also
div1 : {0, . . . , B 2 − 1} → B,
17
x 7→ ⌊x/B⌋
und
mod1 : {0, . . . , B 2 − 1} → B,
x 7→ ⌊x mod B⌋
Dies ermöglicht eine effizientere Berechnung gegenüber dem Fall, dass beide
Operanden geheim sind. Die Festlegung auf B als Divisor ergibt sich durch die
spätere Anwendung, der Aufwand ist für jede Wahl gleich. Die Funktionen für
zwei geheime Operanden werden für die Langzahlarithmetik nicht benötigt.
Der Übertrag einer Addition oder Multiplikation kann einfach mittels Division des Egebnisses durch B berechnet werde. Oft wird der erste Operand nur
aus dem eingeschränkten Wertebereich {0, .., 2B − 1} statt {0, .., B 2 − 1} stammen. Der Wert 2B − 1 ist das maximale Ergebnis einer einstelligen Addition
plus einem eventuellen Übertrag, da (B − 1) + (B − 1) + 1 = 2B − 1 gilt. Die
Funktionen rediv1 und remod1 bezeichnen die Division und Modulo-Operation
auf dem eingeschränkten Wertebereich, ebenfalls mit der Basis B als zweitem
festen Operanden. Es gilt also
rediv1 : {0, . . . , 2B − 1} → {0, 1},
x 7→ ⌊x/B⌋
und
remod1 : {0, . . . , 2B − 1} → {0, . . . , B − 1},
x 7→ x mod B
Diese Funktionen werden wie in Abschnitt 4.3.1 beschrieben durch Polynome
dargestellt. Für die verschiedenen div und mod Operationen ergibt sich damit
folgender Multiplikationsaufwand:
M(div1) = M(mod1) =
M(rediv1) = M(remod1) =
B2 − 2
2B − 2
Oft werden bei einer Division sowohl der Quotient, als auch der Rest als
Ergebnis benötigt. Der Rest kann lokal ohne Multiplikationsaufwand aus dem
Quotienten berechnet werden, denn für a div B = q gilt a mod B = a − q · B.
Die Berechnung von Quotient und Rest wird mit divmod bezeichnet und es gilt
M(divmod1) = M(div1) = B 2 − 2
M(redivmod1) = M(rediv1) = 2B − 2
5.1.2
Addition und Multiplikation von Kurzzahlen
Die Addition zweier einstelliger Zahlen kann lokal ausgeführt werden. Das Ergebnis muss aber bezüglich B reduziert werden. Es müssen Übertrag und Rest
bestimmt werden, also eine Division und eine Modulo Operation durchgeführt
werden. Hier kann das eingeschränkte redivmod1 verwendet werden, da das Ergebnis einer Addition höchstens (B − 1) + (B − 1) = 2B − 2 ist. Ob eines oder
beide Argumente geheim sind, spielt für den Aufwand keine Rolle. Die Addition
sei mit add bezeichnet und hat einen Aufwand von
M(add) = M(redivmod1) = 2B − 2 .
Die Multiplikation benötigt eine verteilte Multiplikation zur Berechnung des
Ergebnisses, falls beide Zahlen geheim sind. Ausserdem wird wieder eine Kombination aus Division und Modulo Operation für die Berechnung des Übertrags
18
und des Restes benötigt, in diesem Falle eine divmod1 Operation, da das maximale Ergebnis hier (B − 1) · (B − 1) = B 2 − 2B + 1 beträgt. Die Multiplikation
wird mit mul bezeichnet und hat einen Aufwand von
M(mul1) = M(divmod1) = B 2 − 2
für den Fall eines geheimen Operanden und
M(mul2) = M(divmod1) + 1 = B 2 − 1
für den Fall zweier geheimer Operanden.
5.1.3
Geheime Vergleiche
Die Vergleichsoperatoren <, >, ≤, ≥ können für geheime Kurzzahlen a, b mit
einer Division, genauer, einer rediv1 Operation, berechnet werden. Die folgende
Tabelle gibt die entsprechenden arithmetischen Ausdrücke für die Operatoren
an. Das Ergebnis der Ausdrücke ist jeweils ein verteilter boolescher Wert.
a>b
(B − 1 + a − b) rediv1 B
a≥b
(B + a − b) rediv1 B
a<b
1 − ((B + a − b) rediv1 B)
a ≤ b 1 − ((B − 1 + a − b) rediv1 B)
Da a, b einstellige Zahlen mit a, b ∈ B = {0, .., B − 1} sind, liegen die durch
B zu dividierenden Ausdrücke für a > b und a ≤ b im Intervall [0, 2B − 2]
und für a ≥ b und a < b im Intervall [1, 2B − 1]. Damit kann an dieser Stelle
die rediv1 Operation benutzt werden. Der Wertebereich von rediv1 ist um
eins größer als hier benötigt. Der Klarheit und Einfachheit halber benütze ich
die Funktion hier aber trotzdem, eine Optimierung an dieser Stelle hat keine
signifikante Auswirkung. Alle vier Operatoren haben also einen Aufwand von
M(rediv1) = 2B − 2.
Gleichheit und Ungleichheit lassen sich durch den ≥ und ≤ Operator über
den Zusammenhang a = b ⇔ (a ≥ b) ∧ (a ≤ b) darstellen, benötigen dann
aber die doppelte Anzahl an Multiplikationen plus dem Aufwand für die UNDVerknüpfung. Die UND-Verknüpfung kann wie in Abschnitt 3.1 dargestellt mit
einer Multiplikation realisiert werden. Allerdings fällt kein weiterer Speicherbedarf an. Die in Abschnitt 4.3.2 vorgestellte generelle Methode benötigt |F| − 1
Multiplikatioen. Man kann den Gleichheitsoperator aber auch direkt über ein
Polynom berechnen. Die Differenz a − b ist 0, falls a und b gleich sind und
ungleich 0, falls sie ungleich sind. Das Ergebnis von a − b liegt im Intervall
[−(B − 1), B − 1] und die Berechnung des zugehörigen Polynoms vom Grad
2B − 2 benötigt damit 2B − 3 Multiplikationen. Um alle Vergleichsoperatoren mit einheitlichem Aufwand betrachten zu können, setze ich den Aufwand
auch auf 2B − 2 fest. Die Anzahl geheimer Operatoren ist unerheblich, da der
Aufwand für die Subtraktion davon nicht abhängt. Die Vergleichsoperatoren
{<, >, ≤, ≥, =} seien als Oberbegriff mit cmp bezeichnet und es gilt somit
M(cmp) = 2B − 2 .
Für die Division von Langzahlen werden wir einen Vergleich zwischen einer Zahl a ∈ {0, .., (B − 1)2 } und einer Zahl b ∈ {0, ..., B 2 − 1} berechnen
19
Algorithmus 1 : Vergleich auf Kleiner
Eingabe : a = (an−1 ...a0 ), b = (bn−1 ...b0 )
Ausgabe : r = 1 falls a < b, r = 0 sonst
1 r ← 0;
2 für i ← 0 bis n − 1 tue
3
wenn ai < bi dann
4
r ← 1;
5
sonst
6
wenn ai > bi dann
7
r ← 0;
müssen (siehe Algorithmus 6, Zeile 9). Ein Vorgehen wie oben dargestellt ist
nicht möglich, da Überläufe nicht mehr eindeutig festgestellt werden können.
Eine direkte Berechnung der Funktion über ein Polynom wäre sehr aufwendig,
da beide Argumente des Vergleichs geheim sind und damit ein Polynom in zwei
Variablen ausgewertet werden müsste.
Eine andere Möglichkeit ist, die Operanden zu erst in zweistellige Langzahlen
umzuwandeln und dann zu vergleichen. Für die Umwandlung einer Zahl x ∈
0, . . . , B 2 − 1 in eine zweistellige Langzahl (y1 y0 ) werden die einzelnen Stellen
folgendermassen berechnet:
y1 = x/B,
y0 = x mod B
Die Berechnung benötigt eine Division und eine Modulo Operation und hat
damit einen Aufwand von M(divmod1) Multiplikationen. Ein Verfahren zum
Vergleich zweier Langzahlen gebe ich in Algorithmus 1 exemplarisch für den <
Operator an. Für die anderen Operatoren funktioniert das Verfahren analog.
Die Stellen der Langzahlen werden paarweise verglichen, angefangen von der
niederwertigsten Stelle. Im Normalfall würde man bei der höchstwertigen Stelle
beginnen und abbrechen, sobald das Ergebnis klar ist. Da die Langzahlen aber
aus geheimen Werten bestehen, kann nicht vorher abgebrochen werden. Die
boolsche Variable r gibt zu jedem Zeitpunkt an, ob a < b gilt. Sie wird mit 0
initialisiert. Gilt nun für eine Stelle ai < bi , ist a bis zu dieser Stelle kleiner als
b und r wird auf 1 gesetzt. Gilt ai > bi , ist a bis zu dieser Stelle größer als b
und r wird auf 0 gesetzt und gilt ai = bi bleibt der Wert von r gleich, da diese
Stelle keine Veränderung der Relation beider Zahlen bringt.
Die Auswertung der beiden Bedingungen in Zeile 3 und 6 benötigt jeweils
M(cmp) Multiplikationen, das Ergebnis ihrer Auswertung sei mit b1 und b2
bezeichnet. Die Verzweigung wird durch den arithmetischen Ausdruck
r = b1 · 1 + (1 − b1 )(b2 · 0 + (1 − b2 )r)
dargestellt. Dieser lässt sich zu r = b1 − (1 − b1 )(1 − b2 )r vereinfachen und
benötigt damit nur 2 Multiplikationen. Die Schleife hat n Durchläufe und es
ergibt sich damit ein Gesamtaufwand von
M(lcmpn ) = n(2M(cmp) + 2) = n(4B − 2) = 4Bn − 2n .
20
Der Gesamtaufwand für die Umwandlung und den Vergleich der Zahlen beträgt
also
2M(divmod1) + M(lcmp2 )
= 2(B 2 − 2) + 2(4B − 2)
= 2B 2 + 8B − 8 .
5.2
Rechnen mit Langzahlen auf arithmetischen Schaltkreisen
Im folgenden Abschnitt werde ich nun die Grundrechenarten (Addition, Subtraktion, Multiplikation und Division), sowie die modulare Exponentiation auf
geheimen Langzahlen einführen. Ich setze dafür die aus [Knu98], [Wel98] und
[Cor01] entnommenen Standardverfahren auf einem arithmetischen Schaltkreis
um. Es seien im folgenden a, b Langzahlen in b-adischer Darstellung mit Basis
B.
5.2.1
Addition
Die Addition entspricht der Schuladdition. Für jede Stelle muss eine einstellige
Addition mit Reduktion und Übertragsbildung durchgeführt werden. Hierzu
reichen die eingeschränkten rediv1 und remod1 Operationen aus. Es muss also
pro Stelle eine Division und eine lokale Multiplikation zur Berechnung des Restes
ausgeführt werden. In Algorithmus 2 wird das Verfahren dargestellt. Für eine
Addition von zwei n-stelligen Zahlen ergibt das einen Multiplikationsaufwand
von
M(laddn ) = n · M(redivmod1) = 2Bn − 2n .
Der Aufwand hängt dabei immer von der Zahl mit den meisten Stellen ab,
ist eine Zahl kürzer bringt das keinen Vorteil, da der Algorithmus trotzdem
komplett durchgerechnet werden muss.
Algorithmus 2 : ladd
Eingabe : a = (an−1 . . . a0 ), b = (bn−1 . . . b0 )
Ausgabe : s = (sn . . . s0 ) = a + b
1 c ← 0;
2 für i ← 0 bis n − 1 tue
3
si ← (ai + bi + c) mod B;
4
c ← (ai + bi + c)/B;
5
sn ← c;
5.2.2
Subtraktion
Algorithmus 3 subtrahiert zwei Langzahlen a und b voneinander. Das Verfahren
setzt im wesentlichen die Schulmethode um. In Zeile 3 wird die aktuelle Stelle
berechnet, in Zeile 4 wird die Borge für diese Stelle berechnet. Für den Fall
a > b beinhaltet s das Ergebnis der Subtraktion und es gilt c = 0. Für a <
b ist das Ergebnis negativ. Das Ergebnis s ist dann das B-Komplement der
21
Algorithmus 3 : lsub
Eingabe : a = (an−1 ...a0 ), b = (bn−1 ...b0 )
Ausgabe : s = (csn−1 ...s0 ) = a − b
1 c ← 0;
2 für i ← 0 bis n − 1 tue
3
si ← B + ai − bi − c mod B;
4
c ← 1 − (B + ai − bi − c)/B;
Subtraktion und es gilt c = 1, das heisst, der letzte Übertrag ist eins. Falls
a = b gilt, sind alle Ergebnisstellen null und es gilt auch c = 0. Die Addition
von B auf das Subtraktionsergebnis in Zeile 3 und 4 ist notwendig, damit das
Ergebnis der Berechnung im Intervall [0, B−1] liegt. Ansonsten kann es zu einem
Unterlauf im Körper kommen und die Resultate der div und mod Operationen
wären unbrauchbar. Es genügen wieder die eingeschränkten rediv1 und remod1
Operationen, da 0 ≤ B +ai −bi −c < 2B gilt. Eine Subtraktion zweier n-stelliger
Zahlen hat damit einen Aufwand von
M(lsubn ) = n · M(redivmod1) = 2Bn − 2n .
Auch hier hängt der Aufwand, wie bei der Addition, nur von der Zahl mit den
meisten Stellen ab.
5.2.3
Multiplikation
Das einfachste Verfahren zur Multiplikation zweier Langzahlen orientiert sich
an der Schulmethode und hat einen zeitlichen Aufwand von O(n2 ). Mit der
Karatsuba-Multiplikation oder der FFT existieren hierfür schnellere Verfahren,
ich stelle nur die Umsetzung des einfachen Verfahrens in Algorithmus 4 vor. Wie
in der Schulmethode werden über die zwei Schleifen alle Stellen miteinander
multipliziert (Zeile 5). In der Variable c ist der Übertrag aus der vorhergehenden Stelle gespeichert. Im Unterschied zur Schulmethode werden nicht erst alle
Multiplikationen ausgeführt, um danach die Ergebnisse zu addieren, sondern
die Ergebnisse der Multiplikation werden für jede Stelle gleich fortlaufend aufaddiert. In der Variable w werden diese Werte für jede Stelle gespeichert. Am
Ende des Algorithmus steht in w das Gesamtergebnis.
Der Schleifenrumpf (Zeilen 5 bis 7) benötigt M(divmod1) + 1 Multiplikationen. Insgesamt wird der Schleifenrumpf m · n mal durchlaufen, wobei m und n
die Stelligkeiten der beiden Langzahlen sind. Es ergibt sich ein Multiplikationsaufwand von
M(lmul2m,n ) = mn(M(divmod1) + 1) = B 2 mn − mn.
Für die Multiplikation einer öffentlichen Langzahl mit einer geheimen kann der
gleiche Algorithmus verwendet werden, allerdings ist die Multiplikation in Zeile
5 dann öffentlich, womit der Schleifenrumpf nur M(divmod1) Multiplikationen
benötigt. Der Gesamtaufwand beträgt dann mnM(divmod1) für die Stelligkeiten m und n. Es ist dabei nicht relevant, welche der beiden Zahlen öffentlich
und welche geheim ist. Es gilt also:
M(lmul1m,n ) = mnM(divmod1) = B 2 mn − 2mn
22
Algorithmus 4 : lmul
Eingabe : u = (um−1 ...u0 ), v = (vn−1 ...v0 )
Ausgabe : w = u · v = (wm+n−1 ...w0 )
1 w ← 0;
2 für i ← 0 bis m − 1 tue
3
c ← 0;
4
für j ← 0 bis n − 1 tue
5
t ← ui · vj + wi+j + c;
6
c ← t/B;
7
wi+j ← t mod B;
wj+m ← c;
8
5.2.4
Kurze Division mit Rest
Bevor ich die allgemeine Division mit Rest vorstelle, betrachte ich den Spezialfall einer Division mit einstelligem Divisor. Diese Operation sei mit shdiv2
bezeichnet und kann effizienter als eine Langzahldivision mit beliebig langem
Divisor ausgeführt werden. Wie man im nächsten Abschnitt noch sehen wird,
muss bei der allgemeinen Langzahldivision aufwendig bestimmt werden, wie oft
der Divisor in die führenden ein oder zwei Stellen des Dividenden passt. Dies
kann im Falle eines einstelligen Divisors einfach durch eine div Operation berechnet werden. Das in Algorithmus 5 vorgestellte Verfahren liefert den Quotient
und den Rest. Das Verfahren entspricht exakt der Schulmethode. Für jede Stelle
wird geteilt und ein eventueller Rest in die nächste Stelle übertragen.
Der Schleifenrumpf benötigt M(divmod1) Multiplikationen bei m Iterationen. Es ergibt sich also
M(shdiv1) = mM(divmod1) = B 2 m − 2m
für die Anzahl der Multiplikationen. Ich betrachte nur den Fall eines öffentlich
bekannten Divisors, eine Division zweier geheimer Zahlen wird in dieser Arbeit
nicht benötigt. Die kurze Division liefert damit die letzte benötigte Basisoperation, die Division einer zweistelligen Zahl durch eine einstellige, um die allgemeine
Langzahldivision durchzuführen.
5.2.5
Verzweigungen
Verzweigungen mit Langzahlzuweisungen benötigen ebenfalls eine gesonderte
Betrachtung. Es handelt sich dabei zwar nicht um eine Rechenart, ich gehe aber
trotzdem an dieser Stelle darauf ein, da für die Division mit Langzahlen solche
Verzweigungen berechnet werden müssen. Die in Abschnitt 4.1 vorgestellte Methode zur Berechnung von bedingten Verzweigungen im arithmetischen Schaltkreis ist grundsätzlich auch auf Langzahlen anwendbar. Die nötigen Verfahren
zur Addition und Multiplikation von Langzahlen wurden in den vorhergehenden Abschnitten entwickelt. Die für eine Verzweigung nötigen Berechnungen
2 Abk.
für short divison, engl. kurze Division
23
Algorithmus 5 : shdiv
Eingabe : u = (um−1 ...u0 ), v
Ausgabe : q = (qm−1 ...q0 ), r mit u = q · v + r
1 r ← 0;
2 q ← 0;
3 für i ← m − 1 bis 0 tue
4
qi ← (ui + rB)/v;
5
r ← (ui + rB) mod v;
lassen sich aber effizienter als mit den Standardverfahren durchführen. Für die
Langzahl a = (an−1 ...a0 ), die ausgewertete Bedingung b ∈ {0, 1} und die arithmetischen Ausdrücke A1 , A2 betrachte ich die Verzweigung
wenn b dann
a ← A1
sonst
a ← A2
Dabei seien r = (rn−1 ...r0 ) und s = (sn−1 ...s0 ) die Ergebnisse von A1 und A2 .
Zu berechnen ist also der Ausdruck
(an−1 ...a0 ) = b · (rn−1 ...r0 ) + (1 − b)(sn−1 ...s0 ) .
(4)
Bei den Multiplikationen handelt es sich einmal um eine Multiplikation mit dem
Faktor 1 und einmal mit 0. Da es in diesen Spezialfällen nicht zu Überträgen
kommen kann, können alle Stellen mit dem Faktor durchmultipliziert werden,
ohne dass ein Übertrag und Rest berechnet werden muss. Gleichung 4 lässt sich
demnach folgendermassen schreiben:
(an−1 ...a0 ) = (b · rn−1 ...b · r0 ) + ((1 − b)sn−1 ...(1 − b)s0 )
Damit benötigt eine Langzahlzuweisung innerhalb einer bedingten Verzweigung
2n Multiplikationen, wobei n die Stelligkeit ist, zuzüglich des Aufwandes für die
Addition. Es ergibt sich
M(lifn ) = 2n + M(laddn ) = 2Bn .
5.2.6
Division mit Rest
Um die Grundrechenarten zu vervollständigen, fehlt nun noch die allgemeine
Division von Langzahlen. Dies ist auch die aufwendigste Operation. Auch hierbei wird prinzipiell die Schulmethode benützt, allerdings ist die Umsetzung in
einen Algorithmus ein wenig schwieriger, da beim Rechnen von Hand für jede
Ergebnisstelle eine Abschätzung getroffen wird, die nun in ein algorithmisches
Verfahren umgesetzt werden muss. Letzlich reduziert sich das Problem darauf,
eine n+1-stellige Zahl durch den n-stelligen Divisor zu teilen. Dies liefert jeweils
eine Ergebnisstelle. Man betrachte das klassische Verfahren. Um die Zahl 355938
durch 427 zu teilen, dividiert man 3559 durch 427, was 8 Rest 133 ergibt. Die
8 ist die erste Ergebnisstelle und man fährt fort indem man an den Rest eine
weitere Stelle anhängt und damit 1333 durch 427 teilt, was 3 Rest 52 ergibt.
Nun wird noch 528 durch 427 geteilt, was 1 Rest 101 ergibt und man erhält als
24
Gesamtergebnis 831 Rest 101. Die Berechnung der einzelnen Ergebnisstellen, ist
bereits eine Langzahldivision. Ein Mensch schätzt hier eine Lösung relativ leicht
ab, da der Dividend nur um eine Stelle größer als der Divisor ist.
In [Knu98] ist ein präzises Verfahren zur Berechnung des Quotienten angegeben. Seien u = (un un−1 . . . u0 ) und v = (vn−1 . . . v0 ) Langzahlen, wobei u
dem aktuellen Dividend und v dem Divisor entspricht und es gilt u/v < B.
Aufgabe ist es nun also den Quotienten q mit q = ⌊u/v⌋ zu bestimmen. Knuth
gibt folgende Näherung q̂ für q an
un B + un−1
q̂ = min
,B − 1
vn − 1
Theoreme A und B in [Knu98], Kapitel 4.3.1 besagen, dass falls vn−1 ≥ ⌊B/2⌋
ist, so gilt für q̂
q̂ − 2 ≤ q ≤ q̂
Die Näherung q̂ ist in diesem Fall damit nie kleiner als q und höchstens 2 zu groß.
Um die Bedingung vn−1 ≥ ⌊B/2⌋ zu erfüllen, werden u und v mit ⌊B/(vn−1 +1)⌋
multipliziert. Diese Normalisierung ändert den Quotienten u/v nicht und erhöht
die Stellenanzahl in v nicht. Die Stellenanzahl von u erhöht sich möglicherweise
um eins. Durch diese Normalisierung ist die Bedingung immer erfüllt (siehe
[Knu98], Kapitel 4.3.1, exercise 23).
n−1
⌋, B − 1). Man kann die Wahl von
Man wähle wie oben q̂ = min(⌊ un B+u
vn −1
q̂ noch weiter verbessern, so dass in jedem Fall entweder q̂ = q oder q̂ = q + 1
gilt, q̂ also maximal um eins zu groß ist. Dies erreicht man, indem man testet,
ob q̂vn−2 > (un B + un−1 − q̂vn−1 )B + un−2 gilt. Wenn nicht, wird q̂ um eins
vermindert und der Test wiederholt. Damit werden alle Fälle, in denen q̂ um
zwei zu groß ist und fast alle, in denen q̂ um eins zu groß ist, ausgeschlossen
(siehe [Knu98], Kap. 4.3.1, Aufgabe 19,20). Mit diesen Vorüberlegungen kann
nun ein Verfahren zur Langzahldivision angegeben werden.
Für zwei Langzahlen u = (um+n−1 . . . u0 ) und v = (vn−1 . . . v0 ) sei q =
(qm . . . q0 ) = ⌊u/v⌋ der Quotient und r = (rn−1 . . . r0 ) = u mod v der Rest der
Division von u durch v. Das Verfahren zur Berechnung von q und r ist nun:
1. Normalisierung: Berechne den Skalierungsfaktor d = ⌊B/(vn−1 + 1)⌋
und setze (um+n um+n−1 . . . u0 ) = d(um+n−1 . . . u0 ) und (vn−1 . . . v0 ) =
d(vn−1 . . . v0 ).
2. Initialisierung: Setze j = m, über diese Variable wird iteriert, das Ergebnis der Division hat m + 1 Stellen.
3. Berechnung der nächsten Quotientenstelle: Setze
un B + un−1
,B − 1 .
q̂ = min
vn − 1
Teste ob q̂vn−2 > (un B + un−1 − q̂vn−1 )B + un−2 gilt, wenn nicht, setze
q̂ = q̂ − 1 und wiederhole den Test.
4. Multiplizieren und Subtrahieren: Setze
(uj+n uj+n−1 . . . u0 ) = (uj+n uj+n−1 . . . u0 ) − q̂(vn−1 . . . v0 ) .
25
Falls das Ergebnis negativ ist, war q̂ um eins zu groß. In diesem Fall setze
q̂ = q̂ − 1 und u = u + v. Setze qj = q̂.
5. Iteration: Setze j = j − 1. Falls j ≥ 0 gehe zu Schritt 3.
6. Denormalisierung: In der Variable (qm . . . q0 ) steht der gesuchte Quotient. Setze r = ⌊(un−1 . . . u0 )/d⌋, dies ist der gesuchte Rest.
Algorithmus 6 gibt ein entsprechendes Programm für die Langzahldivision
in Pseudocode an. Die Normalisierung findet in den Zeilen 1 bis 3 statt. In den
Zeilen 5 bis 7 wird die Näherung der Quotientenstelle nach Schritt 3 berechnet
und direkt in qj gespeichert, eine Zwischenvariable q̂ wird nicht benötigt. Sie
ist in der informellen Beschreibung des Verfahrens nur der Übersichtlichkeit
halber vorhanden. In Zeile 8 wird der Rest für das genäherte q berechnet. Dieser
wird für den Test aus Schritt 3 benötigt, er entspricht dort dem geklammerten
Ausdruck. Der Test selbst wird in den Zeilen 9 bis 13 durchgeführt. Hier ist
zu beachten, dass nach der ersten Korrektur von qj der neue Rest aus dem
alten durch Addition von vn−1 berechnet wird, das spart eine Multiplikation.
Das Multiplizieren und Subtrahieren (Schritt 4) wird in den Zeilen 14 bis 17
durchgeführt. Hier ist zu beachten, dass die Ergebnislangzahl (uj+n+1 . . . uj )
Algorithmus 6 : ldiv
Eingabe : u = (um+n−1 ...u0 ), v = (vn−1 ...v0 )
Ausgabe : q = (qm ...q0 ), r = (rn−1 ...r0 ) mit u = q · v + r
/* Normalisierung
1 d ← B/(vn−1 + 1);
2 u ← d · u;
3 v ← d · v;
4 für j ← m bis 0 tue
/* Berechnung der nächsten Quotientenstelle
5
qj ← (uj+n B + uj+n−1 )/vn−1 ;
6
wenn qj ≥ B dann
7
qj ← B − 1;
8
9
10
11
12
13
14
15
16
17
18
19
*/
*/
c ← uj+n B + uj+n−1 − qj vn−1 ;
wenn qj vn−2 > Bc + uj+n−2 dann
qj ← qj − 1;
c ← c + vn−1 ;
wenn qj vn−2 > Bc + uj+n−2 dann
qj ← qj − 1;
/* Multiplizieren und Subtrahieren
(uj+n+1 ...uj ) = (uj+n ...uj ) − qj (0vn−1 ...v0 );
wenn uj+n+1 = 1 dann
qj ← qj − 1;
(uj+n ...uj ) = (uj+n ...uj ) + (0vn−1 ...v0 );
/* Denormalisierung
(un−1 ...u0 ) = (un−1 ...u0 )/d;
r ← (un−1 ...u0 );
*/
*/
26
1
0
0
2
M(lmul1m+n,1)
B 2 (m + n) − 2m − 2n
3
0
0
4 m + 1 Wiederholungen Zeile 5 - 17
5
M(shdiv12 )
2B 2 − 4
6
M(cmp)
2B − 2
7
2
2
8
0
0
9
2M(divmod1) + M(lcmp2 )
2B 2 + 8B − 8
10
0
0
11
2
2
12
2M(divmod1) + M(lcmp2 )
2B 2 + 8B − 8
13
4
4
14
M(lsubn+1 ) + M(lmul11,n ) B 2 n + 2Bn + 2B − 4n − 2
15
M(cmp)
2B − 2
16
2
2
17
M(laddn+1 ) + M(lifn+1 )
4Bn + 4B − 2n − 2
18
M(shdiv1n )
B 2 n − 2n
Tabelle 1: Aufwand der Langzahldivision gegeben durch die benötigten verteilten Multiplikationen für jede Zeile von Algorithmus 6.
vorne eine Stelle mehr besitzt, als auf den ersten Eindruck nötig scheint, hat. In
dieser Stelle steht eine 1, falls das Ergebnis der Subtraktion negativ war, sonst
eine 0 (siehe Abschnitt 5.2.2). Nach dieser Stelle wird also verzweigt und falls
das Ergebnis negativ ist, dann ist qj um eins zu groß und wird anschliessend
in Zeile 16 um eins reduziert. In den Stellen (uj+n . . . uj ) steht dann das BKomplement des Ergebnisses, dieses kann dann einfach durch Rückaddition von
(vn−1 . . . v0 ) korrigiert werden. Ein eventueller Übertrag kann ignoriert werden,
er würde sich mit der Borge aus der Subtraktion ausgleichen.
Ich bestimme nun den Aufwand für den Fall eines öffentlich bekannten Divisors, da dies der für RSA interessante Fall ist. Bei der Normalisierung wird
eine Langzahl mit einem öffentlich bekannten Skalar multipliziert. Die Operationen in Zeile 1 und 3 haben öffentliche Operanden. Bei der Berechnung der
Quotientenstelle ist bei der Auswertung der Bedingungen in Zeile 9 und 12 zu
beachten dass der Ausdruck Bc + uj+n−2 im Intervall [0, .., B 2 ) liegt. Die zu
vergleichenden Zahlen werden wie in Abschnitt 5.1.3 beschrieben, in zweistellige Langzahlen umgewandelt und dann verglichen. Die gesamte Verzweigung
von Zeile 9 bis Zeile 13 wurde schon in Abschnitt 4.1 exemplarisch in arithmetische Ausdrücke umgewandelt. Bei der Multiplikation und Subtraktion ist zu
beachten, dass in Zeile 17 eine Langzahlzuweisung innerhalb einer Verzweigung
steht. Diese wird wie in Abschnitt 5.2.5 gezeigt behandelt. Die Denormalisierung benötigt noch eine shdiv Operation. Tabelle 1 gibt den Aufwand für jede
Zeile an.
Es ergibt sich damit der Gesamtaufwand von
M(ldivm,n )
= mnB 2 + 3nB 2 + 7mB 2 + 6B 2 + 6mnB + 6nB
+ 26mB + 26B − 6mn − 10n − 20m − 18
27
Multiplikationen. Für den Spezialfall m = 0, also der Division gleich langer
Zahlen ergibt sich ein Aufwand von
M(ldiv10,n ) = 3nB 2 + 6B 2 + 6nB + 26B − 10n − 18
Multiplikationen.
5.2.7
Modulare Exponentiation
Als letzte Rechenoperation betrachte ich die Exponentiation zweier Langzahlen a und b modulo einer Zahl n, also die Berechnung von ab (mod n). Dies
wird auch als modulare Exponentiation bezeichnet. Diese Operation wird für
die Implementierung des RSA-Verfahrens benötigt, ich betrachte nur den hierfür
benötigten Fall des öffentlich bekannten Modulus. Der Exponent sei ausserdem
in Binärdarstellung gegeben, also als geheime Langzahl zur Basis 2. Ein effizientes Verfahren zur Berechnung ist der Square and Multiply Algorithmus. Dieser
bietet sich besonders an, da er einfach auf einem arithmetischen Schaltkreis
zu implementieren ist. Ich gebe ihn in Algorithmus 7 an (siehe auch [Cor01],
Kapitel 31.6).
Das zugrunde liegende Verfahren lässt sich leicht veranschaulichen. Es sei
der Exponent b in Binärdarstellung gegeben, also b = Σki=0 bi ∗ 2i . Es gilt nun
ab
k
=
ab0 +2b1 +...2
=
=
a1·b0 · a2·b1 · . . . · a2 ·bk
ab0 (ab1 (. . . (abn−1 (abn )2 )2 . . . )2 )2
bk
k
(5)
Der Algorithmus berechnet nun den Ausdruck (5) von innen nach aussen, indem in jeder Iteration quadriert wird und je nachdem, ob bi eins oder null ist,
mit a multipliziert wird. Dieser Algorithmus soll nun auf dem arithmetischen
Schaltkreis implementiert werden. Die Basis a der Exponentiation ist entweder
öffentlich oder geheim, der Exponent b ist immer geheim und damit auch die
Variable d, in der am Ende des Algorithmus das Ergebnis steht. Damit sind auch
sämtliche Zwischenergebnisse geheim. Die Zahlen a, b und n sind groß, müssen
also praktisch durch Langzahlen dargestellt werden. Für eine Langzahl x, gebe
lB (x) die Stelligkeit von x zur Basis B an. Die Länge l2 (n) wird vorgegeben3
3 Die
Zahl n entspricht in RSA der Schlüssellänge und ist ein fest gewählter Wert.
Algorithmus 7 : modulare Exponentiation
Eingabe : a, b, n
Ausgabe : ab mod n
1 d ← 1;
2 Sei (bk , bk−1 , ..., b0 ) die Binärdarstellung von b;
3 für i ← k bis 0 tue
4
d ← (d · d) mod n;
5
wenn bi = 1 dann
6
d ← (d · a) mod n;
7
return d;
28
und es muss B lB (n) ≥ 2l2 (n) gelten, um alle Zahlen darstellen zu können. Damit
berechnet sich die Stelligkeit der Langzahlen zur Basis B durch
m l (n) · ln 2 l
2
l2 (n)
.
=
lB (n) = logB 2
ln B
Der Exponent b liegt in verteilter binärer Form vor, wobei (bk−1 bk−2 ...b0 ) die
Binärdarstellung von b sei. Das heisst jedes Bit bi von b wird als verteilter Wert
gespeichert. Die bedingte Verzweigung in Zeile 5 und 6 kann damit durch
d = bi ((d · a) mod n) + (1 − bi )d
dargestellt werden. Dieser Ausdruck kann durch Ausklammern von d noch vereinfacht werden, dadurch kann eine Multiplikation für die Verzweigung gespart
werden:
d = d(bi a + (1 − bi )) mod n
Da bi ein boolescher Wert ist, also bi ∈ {0, 1} gilt, kann das Produkt bi a einfacher als eine reguläre Langzahlmultiplikation berechnet werden. Bei einer Multiplikation mit 0 oder 1 können keine Überträge auftreten und es sind somit
nur lB (n) geheime Multiplikationen für die Berechnung des Ergebnisses nötig.
In Abschnitt 5.2.5 ist diese Vereinfachung im Rahmen der Verzweigungen mit
Langzahlen detaillierter dargestellt. Die Addition erfordert eine laddn Operation. Da einer der Summanden immer gleich null ist, kann sich die Stellenzahl
durch die Addition nicht erhöhen. Damit hat das Ergebnis der Addition immer
die Stelligkeit von a, da während der Berechnung nicht klar ist, welcher Summand gleich null ist. Für d gilt lB (d) ≤ lB (n), für die Aufwandsbestimmung
nehme ich lB (d) = lB (n) an, dies gilt für fast alle Iterationen. Die Größe von a
in Bit ist l2 (a) und es gilt l2 (a) ≤ l2 (n). Mit den in Abschnitt 5 eingeführten
Langzahlfunktionen ergibt sich für die modulare Exponentiation ein Aufwand
von
M(modexp) =
k M(lmullB (n),lB (n) ) + M(ldivlB (n),lB (n) )
+ lb (a) + M(laddlB (a) ) + M(lmullB (n),lB (a) )
+ M(ldivlB (a),lB (n) ) .
Falls a öffentlich ist, kann die lmul1 Operation verwendet werden, ansonsten
muss die lmul2 Operation verwendet werden. Auf die Division hat dies keine
Auswirkung, da der Modulus in unserem Fall immer öffentlich ist.
5.3
Binärer Fall
Wählt man als Basis B = 2, gelten die ausgewerteten Komplexitäten in Tabelle
2 nicht mehr, da die Ergebnisse die Ergebnisse der Addition und Multiplikation
zweier einstelliger Zahlen einschliesslich möglicher Überträge im Intervall [0, 3]
liegen. Eine auf einen kleineren Wertebereich eingeschränkte Division entfällt
und es gilt damit
M(div1) = M(rediv1) = 2
Im F2 lässt sich zudem die Division vereinfachen. Da jede Quotientenstelle entweder eins oder null ist, muss nicht aufwendig berechnet werden, wie oft der
Divisor in den momentanen Rest der Division passt. Man kann einfach jede
29
Algorithmus 8 : bldiv
Eingabe : u = (um+n−1 ...u0 )2 , v = (vn−1 ...v0 )2
Ausgabe : q = (qm ...q0 )2 , r = (rn−1 ...r0 )2 mit u = v · q + r
1 c ← 0;
2 für i ← m bis 0 tue
3
wenn c = 0 dann
4
(c ui+n−1 . . . ui ) ← (ui+n−1 . . . ui ) − (vn−1 . . . v0 );
5
sonst
6
(c ui+n−1 . . . ui ) ← (ui+n−1 . . . ui ) + (vn−1 . . . v0 );
7
8
9
10
11
qi ← 1 − c;
wenn c = 0 dann
(rn−1 . . . r0 ) ← (un−1 . . . u0 );
sonst
(rn−1 . . . r0 ) ← (un−1 . . . u0 ) + (vn−1 . . . v0 );
Quotientenstelle mit eins annehmen und falls nach dem multiplizieren und subtrahieren das Ergebnis negativ ist, kann der Schritt rückgängig gemacht werden
und die nächste Stelle des Dividenten mit betrachtet werden. Algorithmus 8
stellt das Verfahren dar. Da die Variable l aus {0, 1} ist, können die Bedingungen in Zeile 2 und 7 durch Berechnung von 1 − l lokal ausgewertet werde. Es
ergibt sich ein Aufwand von
M(bldiv1m,n ) = 8mn + 13n .
5.4
Aufwand der Operationen
Tabelle 2 gibt eine Übersicht über die einzelnen Operationen und ihrem Multiplikationsaufwand, basierend auf der vorgestellten Langzahlarithmetik zur Basis
B. Der Aufwand aller Operationen ist nicht von der Körpergröße abhängig, das
heisst die Anzahl der Multiplikationen bleibt gleich. Allerdings erhöht sich das
kommunizierte Datenvolumen, da bei einem größeren Körper die Elemente des
Körpers in größeren Datenpaketen gespeichert und verschickt werden müssen.
6
RSA
Eine mögliche Anwendung einer Agentenallianz wäre die geheime Berechnung einer Signatur. Eine digitale Signatur ersetzt eine konventionelle Unterschrift. Mit
ihrer Hilfe kann die Herkunft einer Nachricht oder eines Dokuments eindeutig
verifiziert werden. Eine Agentenallianz könnte damit beispielsweise einen Kaufvertrag unterschreiben. Aufgrund der Verbreitung von RSA, soll der Aufwand
einer RSA-Signatur auf einem arithmetischen Schaltkreis untersucht werden.
Für eine Einführung in RSA empfehle ich [Sch96] oder [Cor01], ich gebe hier
nur eine Zusammenfassung des Verfahrens. Ich gehe kurz auf die Verschlüsselung
von Daten mittels RSA ein und darauf aufbauend auf die Verwendung von RSA
zur Erstellung digitaler Signaturen. RSA ist ein public key Kryptoverfahren. Das
heißt, ein Schlüssel besteht aus einem Paar, dem öffentlichen Schlüssel (P, n) und
dem privaten Schlüssel (S, n). Der öffentliche Schlüssel wird öffentlich zugänglich
30
Funktion
logische negation
logisch oder, und
if
ifA1 ,A2
div1, mod1
rediv1, remod1
divmod1
redivmod1
add
mul1
mul2
cmp ∈ {<, >, ≤, ≥, =, 6=}
lcmpn
lifn
laddn
lsubn
lmul1m,n
lmul2m,n
shdiv1n
ldiv1m,n
Operationen
0
1
2
M(A1 ) + M(A2 ) + 2
Multiplikationen
0
1
2
B2 − 2
2B − 2
div1
B2 − 2
rediv1
2B − 2
redivmod1
2B − 2
divmod1
B2 − 2
divmod1 + 1
B2 − 1
2B − 2
2n(cmp + 1)
4Bn − 2n
laddn + 2n
2Bn
n · redivmod1
2Bn − 2n
n · redivmod1
2Bn − 2n
mn · divmod1
B 2 mn − 2mn
mn · divmod1 + mn
B 2 mn − mn
ndivmod1
B 2 n − 2n
2
2
mnB + 3nB + 7mB 2 + 6B 2
+ 6mnB + 6nB + 26mB + 26B
− 6mn − 10n − 20m − 18
Tabelle 2: Multiplikationsaufwand der einzelnen Langzahloperationen
gemacht, der private Schlüssel wird vom Besitzer geheim gehalten. Die Schlüssel
definieren Funktionen, die auf eine Nachricht m angewendet werden können. Die
Funktionen seien mit P () und S() bezeichnet. Die Funktionen sind zueinander
invers, das heißt, es gilt
m
m
= S(P (m))
= P (S(m)) .
Ich stelle die Kommunikation anhand der zwei üblichen Parteien Alice und Bob
dar. Habe nun Alice das Schlüsselpaar (SA , PA ) und Bob das Paar (SB , PB ).
Will nun Bob eine Nachricht m an Alice verschicken, dann verschlüsselt er diese
mit Alices öffentlichem Schlüssel und erhält damit das Chiffrat c = PA (m). und
sendet c an Alice. Alice kann nun mit ihrem privaten Schlüssel die Originalnachricht durch m = SA (c) berechnen.
Eine digitale Signatur kann ebenfalls mithilfe des Schlüsselpaares berechnet
werden. Will Alice zum Beispiel Bob eine signierte Nachricht m′ schicken, dann
berechnet sie einen Hash-Wert H(m′ ) der Nachricht. Dadurch wird die Nachricht
auf eine durch die Hash-Funktion festgelegte Länge gekürzt. Dann berechnet sie
die Signatur s = SA (H(m′ )) und schickt diese mitsamt der Nachricht an Bob.
Bob kann nun überprüfen, ob die Nachricht von Alice kommt, indem er die
Gleichung H(m′ ) = PA (s) prüft.
Für RSA werden die Schlüssel nun nach dem folgenden Verfahren berechnet.
1. Man wählt zwei große Primzahlen p und q mit p 6= q. Groß bedeutet in
31
diesem Fall beispielsweise 1024 Bit. Die Sicherheit des Verfahrens hängt
von der hier gewählten Größe ab.
2. Berechne n = p · q, dieser Wert wird als RSA-Modulus bezeichnet.
3. Wähle eine kleine, ungerade ganze Zahl e, die teilerfremd zu φ(n) ist. φ
ist die Eulersche Phi-Funktion und es gilt φ(n) = (p − 1)(q − 1).
4. Berechne d als das multiplikitativ Inverse zu e modulo φ(n), d existiert
und ist eindeutig definiert.
5. Der öffentliche Schlüssel ist P = (e, n).
6. Der private Schlüssel ist S = (d, n).
Die durch die Schlüssel definierten Funktionen sind nun P (x) = xe mod n und
S(x) = xd mod n, wobei der Definitionsbereich beider Funktionen [0, n − 1] ist.
Die Nachricht muss also kleiner als der Modulus sein.
Die Sicherheit des Verfahrens beruht auf der Schwierigkeit, große Zahlen in
ihre Primfaktoren zu zerlegen. Die Größe von n ist ein Maß für die Sicherheit
der RSA Verschlüsselung. Üblich sind hier Größen von 1024 bis 4096 Bit.
In unserem Szenario wird der geheime Schlüssel unter den Agenten verteilt
geheim gespeichert. Um nun eine digitale Signatur einer Nachricht m zu berechnen, wird der Hash-Wert H(m) der Nachricht berechnet und dieser danach mit
dem geheimen Schlüssel verschlüsselt. Auf die Berechnung des Hashwertes gehe
ich hier nicht ein. Es muss also H(m)d mod n berechnet werden. Der geheim
Schlüssel soll während der Berechnung natürlich stehts geheim bleiben. Der
Kommunikationsaufwand ergibt sich also direkt über den Aufwand der modularen Exponentiation (siehe Kapitel 5.2.7). Tabelle 3 gibt den Kommunikationsaufwand für verchiedene RSA-Moduli und verschiedene Basen der Langzahlen
an. Dabei muss beachtet werden, dass die Nachricht kleienr sein muss, als der
Modulus. In der Tabelle sind beide Werte nur in Bitlängen angegeben. Dies
entspricht letztlich der Betrachtung des worst case, nämlich dass Nachricht und
Modulus die gleiche Länge in Bit haben. Den optimalen Aufwand bekommt
man für die Wahl kleiner Basen. Man sieht deutlich, dass das Verfahren bei
diesen kommunizierten Datenmengen nicht praktisch einsetzbar ist. Auch die
Optimierung für die Basis B = 2 bringen keinen nennenswerten Vorteil. Allerdings erhält man für die Basis B = 2 noch das beste Ergebnis. Die Angabe der
Größe der Datenmengen bezieht sich nur auf die Datenmenge, die ein Agent mit
einem anderen austauscht. Für die Bestimmung der tatsächlichen Größe muss
der angegebene Wert noch mit der Anzahl der Agenten zum Quadrat multipliziert werden. Für alle aufgeführten Basen wird angenommen, dass ein Byte
pro Feldelement kommuniziert wird. In einem realen Szenario käme noch der
Kommunikationsoverhead hinzu.
6.1
Arithmetischer Schaltkreis über dem Ring Zpq
Betrachtet man den RSA Algorithmus bietet sich die Möglichkeit an, im Ring
Zn = Zpq zu rechnen. Auf diese Weise wäre die Rechnung modulo n gewissermassen umsonst, also ohne weiteren Aufwand, gegeben. Eine verteilte Langzahlarithmetik würde ebenfalls entfallen. Die verteilten Werte wären natürlich
immer noch so groß, dass sie als Langzahlen dargestellt werden müssten, aber
32
Modulus Nachricht Basis
1024
1024
3
1024
1024
4
1024
1024
5
1024
1024
6
1024
1024
128
1024
1024
256
2048
2048
3
2048
2048
4
Optimierung für B = 2
1024
1024
2
2048
2048
2
Multiplikationen
12, 3 · 109
13.2 · 109
14, 7 · 109
16, 4 · 109
767, 3 · 109
2312, 1 · 109
98, 0 · 109
104, 7 · 109
Kommunikation
23, 0n2GB
24, 5n2GB
27, 3n2GB
30, 6n2GB
1429, 2n2GB
4306, 6n2GB
182, 5n2GB
195, 0n2GB
11, 3 · 109
90, 3 · 109
21, 0n2GB
168, 2n2GB
Tabelle 3: RSA-Signatur mit Langzahlarithmetik: Multiplikationen und
übertragene Datenmengen, n bezeichnet die Anzahl der Agenten. Für die Datenmengen wird angenommen, dass für jede, der in der Tabelle aufgeführten
Basen, ein Byte pro Feldelement kommuniziert wird. Es wird der worst case
betrachtet, indem Modulus und Nachricht die gleiche Länge in Bit haben. Zu
beachten ist, dass der Modulus trotzdem immer größer als die Nachricht sein
muss.
die entsprechenden Langzahloperationen könnten lokal ohne Kommunikation
durchgeführt werden.
Zu beachten ist, dass im Ring Zpq Nullteiler existieren, es gibt also Elemente, die kein multiplikativ Inverses haben, durch die also nicht dividiert werden
kann. In Abschnitt 2.3 wurde erwähnt, dass für jedes Multiplikationsgatter ein
Tripel von Zahlen erzeugt wird, unter dessen Verwendung die Multiplikation
dann durchgeführt werden kann. Inverse Elemente werden im Protokoll von Hirt
Maurer bei dieser Tripelerzeugung und bei der Rekonstruktion von Geheimnissen benötigt. Für die Tripelerzeugung müssen Lagrangepolynome an der Stelle
0 ausgewertet werden. Genauer müssen die Polynome
wi =
n
Y
j=1
j6=i
αj
αj − αi
für i = 1, ..n
(6)
berechnet werden. Die Differenzen der αi müssen demnach invertierbar sein, es
muss also
(αi − αj ) ∈ Z∗pq mit i, j = 1, ..., n , i 6= j
gelten. Allerdings können die αi von Anfang an so gewählt werden, dass obige
Bedingung erfüllt ist, da es sich um öffentliche einem Agenten von Anfang an
fest zugewiesene Werte handelt. Die Agenten können entsprechend auch schon
die Inversen der Differenzen mitgeliefert bekommen.
Bei der Rekonstruktion von Geheimnissen muss nach Gleichung 2 auf Seite
6 ein lineares Gleichungssystem der Größe 3t + 1 gelöst werden. Hierfür müssen
ebenfalls Inverse berechnet werden. Die Rekonstruktion von Geheimnissen ist
bei jeder geheimen Multiplikation notwendig.
Solange nicht versucht wird von einem Nullteiler das Inverse zu berechnen,
kann man in Zpq rechnen, wie in einem Körper und das Protokoll funktioniert
33
wie bisher. Ist ein zu invertierendes Element allerdings ein Nullteiler bricht
das Protokoll mit einem Fehler ab und das Programm der Agenteallianz oder
zumindest ein Teil davon kann nicht weiter ausgeführt werden. Es stellt sich die
Frage, mit welcher Wahrscheinlichkeit dieser Fehler, also das Auftreten eines
Nullteilers in Zpq auftritt.
Die Größe der Enheitengruppe ist |Z∗pq | = (p − 1)(q − 1) und damit gibt es
pq − (p − 1)(q − 1) = p + q − 1 Nullteiler. Diese sind gerade
{0, p, 2p, . . . , (q − 1)p, q, 2q, . . . , (p − 1)q} .
Ich nehme an, dass alle Zahlen aus Zpq mit gleicher √
Wahrscheinlichkeit in dem
Gleichungssystem auftreten und nähere p und q mit n an. Dies wird natürlich
nie exakt zutreffen, ist aber für die weitere Betrachtung eine sinnvolle Näherung.
Die Wahrscheinlichkeit, einen Nullteiler in Zpq mit einem Versuch zu finden, ist
damit
1 1
1
p+q−1
= + −
P (x 6∈ Z∗pq ) =
pq
q
p pq
Ich nehme an, dass p ≈ n/2 und q ≈ n/2. Damit gilt ungefähr
2
P (x 6∈ Z∗pq ) ≈ √ .
n
Die Möglichkeit, dass während des Protokolldurchlaufs ein Nullteiler zu invertieren ist, kann also vernachlässigt werden.
Zur Berechnung des Chiffrats wird wieder Algorithmus 7 (modulare Exponentiation) benutzt. Der Kommunikationsaufwand verringert sich erheblich,
da die Modulo-Rechnung natürlich entfällt. Die Nachricht a nehme ich wieder
als öffentlich an. Damit müssen pro Schleifendurchgang zwei Multiplikationen
von geheimen Zahlen, einmal die Quadrierung und einmal die Verzweigung,
die durch Ausklammern von d durch eine Multiplikation berechenbar ist. Die
entsprechenden arithmetischen Ausdrücke für die Anweisungen innerhalb der
Schleife lauten dann
d
d
← d·d
← d(bi a + (1 − bi ))
Der Multiplikationsaufwand beträgt damit bei k Iterationen
M(modexpZpq) = 2k .
Man erinnere sich, dass für jedes Bit des Schlüssels ein Schleifendurchlauf stattfindet, k ist also die Schlüssellänge in Bit. Bei einer Schlüssellänge von 1024
bit müssen also 2048 verteilte Multiplikationen berechnet werden. Die einzelnen
Feldelemente haben ebenfalls eine Länge von 1024 bit (= 128 byte). Dies gibt
ein Datenvolumen von insgesamt
2048 · 128 · n2 = 262144 · n2 Byte = 0, 25 · n2 M Byte
Das ergibt bei 10 Agenten ein kommuniziertes Datenvolumen von 25MB. Dies
stellt eine wesentliche Verbesserung gegenüber dem vorgestellten, auf Langzahlarithmetik basierenden Verfahren dar. Tabelle 4 gibt die benötigten Zeiten für
eine Signatur für heute übliche Internetzugänge an.
34
Typ
Nutzer
Downstream/s
Upstream/s
s/Signatur
T1
prof.
1 GBit
1 GBit
0.0021
ADSL
privat
16 MBit
1 MBit
2.1
SDSL
geschätl.
2 MBit
2 MBit
1.04
Kabel
geschäftl.
20 MBit
10 MBit
0.21
Kabel
privat
6 MBit
600 KBit
3.5
Tabelle 4: Benötigte Zeit für eine Signatur
7
AES
Als Beispiel einer symetrischen Chiffre soll der verbreitete AES4 auf einem arithmetischen Schaltkreis umgesetzt werden. Ich werde nur einen kurzen Überblick
über den Algorithmus geben, für eine detaillierte Beschreibung des Verfahrens
siehe [DR99] oder [Bra02], Kapitel 3.2.2.1.2. AES ist ein iteratives Blockchiffre.
Der Eingabedatenblock wird dabei in jeder Iteration den gleichen Transformationen unterzogen und mit dem Schlüssel verknüpft. Das Verfahren kann mit
unterschiedlichen Block- und Schlüssellängen umgehen, ich beschränke mich hier
auf den Fall einer Block- und Schlüssellänge von 256 Bit. Dies ist jeweils der
maximal mögliche Wert. Für diesen Fall werden 14 Iterationen durchgeführt.
AES arbeitet über dem Körper GF (28 ), ein Element des Körpers kann also
durch ein Byte repräsentiert werden. Ein Datenblock wird in vierdimensionale Spaltenvektoren aufgeteilt, wobei jeder Eintrag einem Byte entspricht. Die
Spaltenvekoren werden in einer Matrix A mit 8 Spalten angeordnet:


a00 a01 .. a07
a10 a11 .. a17 

A := 
(7)
a20 a21 .. a27 
a30 a31 .. a37
Diese Matrix wird nun für jede Iteration in vier Schritten transformiert. Es wird
nacheinander eine Bitmustertransformatione, eine Spaltentransformation und
eine Zeilentransformation durchgeführt. Anschliessend wird noch der Schlüssel
addiert.
Bitmustertransformation: Jeder Eintrag der Matrix wird einzeln transformiert. Zuerst wird jedes Byte durch sein multiplikativ Inverses ersetzt.
bij = a−1
ij
(8)
Dann wird eine lineare Transformation (über GF (2)) der Bits durchgeführt:


 
1 0 0 0 1 1 1 1
1

 
  
1 1 0 0 0 1 1 1   1
b0
c0
1 1 1 0 0 0 1 1 
 
   0
b1  
c


1
0
  1 1 1 1 0 0 0 1    

· . +
(9)
 ..  = 


.
 .  1 1 1 1 1 0 0 0  .  0

0 1 1 1 1 1 0 0 
1
b7
c7


 
0 0 1 1 1 1 1 0 
1
0 0 0 1 1 1 1 1
0
4 engl.
Advanced Encryption Standard
35
Diese zwei Transformationen können in einer Substitutionstabelle5 mit 256
Einträgen zusammengefasst werden. Die Gesamttransformation wird mit TB :
GF (28 ) → GF (28 ) bezeichnet.
Zeilentransformation: Die drei unteren Zeilen der Matrix werden zyklisch
nach links verschoben. Die zweite Zeile wird um 1, die dritte um 3 und die vierte
um 4 Positionen verschoben.
Spaltentransformation: Jeder Spaltenvektor wird über eine Matrixmultiplikation abgebildet:
  
  
a0
b0
2 3 1 1
 b 1   1 2 3 1   a1 
  
 =
(10)
 b 2   1 1 2 3  ·  a2 
a3
b3
3 1 1 2
Schlüsseladdition: Zuletzt wird der Schlüssel addiert. Dieser wird hierzu
wie auch der Datenblock als Matrix aufgefasst und die Matrizen werden addiert.
Allerdings wird nicht der Originalschlüssel addiert. Der Originalschlüssel wird
zu Anfang auf eine Länge von 256 ∗ (14 + 1) Bits expandiert und anschliessend
in Blöcke von 256 Bit aufgespalten. Dies sind nun die Schlüssel für die einzelnen
Iterationen. Da eine initiale Schlüsseladdition stattfindet wird ein Schlüssel mehr
benötigt, als Iterationen stattfinden. Die Schlüsselexpansion ist in Algorithmus
9 dargestellt. Dabei gibt nk die Anzahl der Spaltenvektoren des Schlüssels, nb
die Anzahl der Spaltenvektoren eines Datenblockes und nr die Anzahl der Iterationen an. Es gilt in unserem Fall nk = nb = 8 und nr = 14. Die Funktion
c(x) gibt eine Konstante zurück, deren Berechnung hier für unsere Zwecke nicht
interessant ist, da sie keinerlei geheime Multiplikationen erfordert. Die Transformation TR permutiert einen Spaltenvektor in der Form (a, b, c, d) → (b, c, d, a).
Algorithmus 9 : SchlüsselExpansion
Eingabe : Key[nk ] (Schlüssel als Feld von Spaltenvektoren)
Ausgabe : ExKey[nb (nr + 1)] (Spaltenvektoren des expandierten
Schlüssels)
für i ← 0 bis nk − 1 tue
ExKey[i] ← Key[i];
für i ← nk bis nb (nr + 1) − 1 tue
temp ← ExKey[i − 1]; wenn i mod nk = 0 dann
temp ← TB (TR (temp) + c(i/nk );
sonst
wenn i mod nk = 4 dann
temp ← TB (temp);
ExKey[i] = ExKey[i − nk ] + temp;
Um AES auf dem arithmetischen Schaltkreis zu implementieren, liegen zwei
Möglichkeiten nahe. Zum einen kann man den Körper GF (28 ) als Grundkörper
des Schaltkreises nehmen oder man wählt den GF (2) und rechnet auf Bitebene.
Ich untersuche den Aufwand beider Möglichkeiten
5 auch
S-Box genannt
36
Der arithmetische Schaltkreis kann über beliebigen Körpern aufgebaut werden, die Wahl des GF (28 ) bringt keinerlei Einschränkungen mit sich. Allerdings
kann die Bittransformation nicht auf den Shares berechnet werden, da die
einzelnen Bits nicht zugänglich sind. Die Berechnung des multiplikativ Inversen ist ebenfalls nicht durchführbar. Die komplette Transformation muss aus
diesem Grund interpoliert werden und benötigt damit 254 Multiplikationen (da
256 mögliche Eingabewerte) für jedes der 32 Byte. Die Zeilentransformation
benötigt keine Multiplikationen, da es sich um ein einfaches Verschieben von
Körperelementen handelt. Die Spaltentransformation benötigt pro Spaltenvektor 16 Multiplikationen, also 4 pro Byte. Bei der Schlüsselexpansion ist
die Bittransformation TB die einzige Operation, die Multiplikationen erfordert.
Die Permutation TR , die Berechung der Bedingungen für die Verzweigungen und
die Berechnung der Funktion c(x) können lokal durchgeführt werden. Es bleibt
also nur noch zu bestimmen, wie oft die Bittransformation TB ausgeführt wird.
Die Schleife wird insgesamt 112 mal durchlaufen. Damit wird jede Bedingung
in der Verzweigung genau 112/8 = 14 mal wahr, was auf insgesamt 28 Bittransformationen führt. Damit ergibt sich ein Gesamtmultiplikationsaufwand von
14(32 · 254 + 4 · 32) + 28 · 254 = 122696
und einem kommunizierten Datenvolumen von
245392 · n2 Byte.
Im Fall von 10 Agenten ergibt das entsprechend 2, 45MB pro Agent und 24, 5MB
im Gesamten.
Das Rechnen im GF (2) bringt keine Vorteile, da die Berechnung des Inversen ebenfalls interpoliert werden muss und sich ansonsten der Aufwand der
Operationen erhöht und nicht verringert. Man könnte zwar die Matrixmultiplikation in Gleichung 9 berechnen, hat dadurch aber keinen Vorteil, da man sich
die Interpolation in diesem Schritt nicht sparen kann.
8
Abschlussdiskussion
Da ich nur beispielhaft an einzelnen Algorithmen die Realisierbarkeit für Agentenallianzen geprüft habe, ist es nicht möglich, allgemeine Aussagen zu treffen. Allerdings zeigt die Umsetzung des Standart RSA Verfahrens eindeutig
die Grenzen der Allianzen. Der Kommunikationsaufwand ist sicher noch für
einige Jahre zu hoch, um ein solches Programm auf einer Allianz praktisch auszuführen. Daraus kann man schließen, dass auch andere an sich effizient berechenbare Algorithmen, nach einer Transformation auf eine Agentenallianz nicht
mehr praktisch berechenbar sind.
Anderseits sieht man an AES und der Implementierung von RSA über einem
Ring, dass in Spezialfällen ein Algorithmus durchaus effizient implementiert
werden kann. Grundlage ist in beiden Fällen eine geschickte Wahl des Körpers
oder eben des Rings im Falle von RSA. Offen wäre hier noch das Problem, ob
und wie man einzelne geheime Werte von der Darstellung in einem Körper in
die Darstellung in einem anderen Körper transformiert. Diese Notwendigkeit
entsteht möglicherweise, wenn man einzelne Algorithmen aus Effizienzgründen
über speziellen Körpern implementiert.
37
Letztlich wäre es schön ein allgemeines Verfahren zur Hand zu haben, mit
dem beliebige Programme möglichst effizient auf arithmetische Schaltkreise zur
Berechnung durch Agentenallianzen transformiert werden können. Der in dieser
Arbeit verfolgte Ansatz, Kontrollstrukturen eins zu eins umzusetzen mag zwar
anschaulich, aber nicht unbedingt effizient sein.
Aus meiner Sicht, wird man momentan nur sehr kleine und geeignete Programmteile von den Agenten verteilt berechnen lassen. Dies wären dann die besonders sicherheitsrelevanten Funktionen. Trotz verbleibender Probleme beim
Kommunikationsaufwand ist der Ansatz der Agentenallianzen nicht uninteressant, da es der einzige existierende Ansatz ist, Sicherheit und Robustheit für
mobile Softwareagenten zu garantieren.
38
Literatur
[ACCK01] Joy Algesheimer, Christian Cachin, Jan Camenisch, and Günter
Karjoth. Cryptographic security for mobile code. In IEEE Symposium on Security and Privacy, pages 2–11, 2001.
[Bra02]
Gilbert Brands. Verschlüsselungsalgorithmen. Vieweg, 1. aufl. edition, 2002.
[BW86]
E. R. Berlekamp and L. Welch. Error correction of algebraic block
codes. US Patent Number 4,633470, 1986.
[Cor01]
Thomas H. Cormen. Introduction to algorithms. MIT Press, 2. ed.
edition, 2001.
[DR99]
J. Daemen and V. Rijmen.
Aes proposal: Rijndael, 1999.
http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf.
[EM03]
Regine Endsuleit and Thilo Mie. Secure multi-agent computations.
In Hamid R. Arabnia and Youngsong Mun, editors, Security and
Management, pages 149–155. CSREA Press, 2003.
[GRR98]
Rosario Gennaro, Michael O. Rabin, and Tal Rabin. Simplified vss
and fact-track multiparty computations with applications to threshold cryptography. In PODC, pages 101–111, 1998.
[HH94]
Günther Hämmerlin and Karl-Heinz Hoffmann. Numerische Mathematik. Springer, 4., nochmals durchges. aufl. edition, 1994.
[HM01]
Martin Hirt and Ueli M. Maurer. Robustness for free in unconditional multi-party computation. In Joe Kilian, editor, CRYPTO,
volume 2139 of Lecture Notes in Computer Science, pages 101–118.
Springer, 2001.
[Knu98]
Donald E. Knuth. The art of computer programming, volume 2.
Addison-Wesley, 3. ed. edition, 1998.
[Sch96]
Bruce Schneier. Applied cryptography. Wiley, 2. ed. edition, 1996.
[Sha79]
Adi Shamir. How to share a secret. Commun. ACM, 22(11):612–613,
1979.
[Wel98]
Michael Welschenbach. Kryptographie in C und C++. Springer,
1998.
39
Herunterladen