Implementierung und Untersuchung von Algorithmen zur Produktion von pseudozufälligen Werten
←
→
Transkription von Seiteninhalten
Wenn Ihr Browser die Seite nicht korrekt rendert, bitte, lesen Sie den Inhalt der Seite unten
Gottfried Wilhelm Leibniz Universität Hannover Fakultät für Elektrotechnik und Informatik Institut für Theoretische Informatik Bachelorarbeit Implementierung und Untersuchung von Algorithmen zur Produktion von pseudozufälligen Werten Tim Martin Berger Matrikelnr. 1001 1842 Erstprüfer & Betreuer: PD Dr. Arne Meier Zweitprüfer: Prof. Dr. Heribert Vollmer Hannover, den 8. April 2021
Erklärung der Selbstständigkeit Hiermit versichere ich, die vorliegende Bachelorarbeit selbstständig verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel verwendet zu haben. Die Arbeit hat in gleicher oder ähnlicher Form noch keinem anderen Prüfungsamt vorgelegen. Hannover, den 8. April 2021 Tim Martin Berger
Inhaltsverzeichnis 1 Einleitung 1 1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Aufbau der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 Theoretische Grundlagen 2 2.1 Zufall und Pseudozufall . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2.2 Pseudozufallsgeneratoren . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2.1 Prädiktoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2.2 Statistische Tests . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2.2.3 Einwegfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . 5 3 Anforderungen an Pseudozufallsgeneratoren 6 3.1 Effizienz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 3.2 Kryptographische Sicherheit . . . . . . . . . . . . . . . . . . . . . . . . 7 3.2.1 Zufälligkeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.2.2 Unvorhersagbarkeit . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.2.3 Blackboxing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.2.4 Wahl des Seeds . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 4 Statistische Tests 9 4.1 Frequency (Monobit) Test . . . . . . . . . . . . . . . . . . . . . . . . . 10 4.2 Runs Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 4.3 Test for the Longest Run of Ones in a Block . . . . . . . . . . . . . . . 12 4.4 Cumulative Sums Test . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 4.5 Weitere Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 5 Blum-Micali-Generator 17 5.1 Konzept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.2 Implementierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 5.2.1 Diskrete Exponentialfunktion . . . . . . . . . . . . . . . . . . . 19 5.2.2 Hardcore-Prädikat . . . . . . . . . . . . . . . . . . . . . . . . . 19 5.2.3 Der Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
5.3 Hilfsfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.3.1 Teilerfremdheit . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.3.2 Primitivwurzeln . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 5.4 Untersuchung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 5.4.1 Patternerzeugung in Abhängigkeit der Primzahl p . . . . . . . . 23 5.4.2 Der Seed x gibt den Startwert des Patterns vor . . . . . . . . . 24 5.4.3 Die Menge möglicher Pattern ist durch g gegeben . . . . . . . . 25 5.4.4 Niedrige Seeds x fallen aus dem Muster . . . . . . . . . . . . . . 27 5.4.5 Wahl des Tests für Patternerkennung entscheidend . . . . . . . 28 5.4.6 Schlussfolgerung . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 6 Mersenne-Twister-Generator 32 6.1 Implementierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 6.1.1 Twist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 6.1.2 Ausgabe der Pseudozufallszahl . . . . . . . . . . . . . . . . . . . 34 6.2 Untersuchung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 6.2.1 Bedeutung des Seeds . . . . . . . . . . . . . . . . . . . . . . . . 35 6.2.2 Rolle der Ausgabefunktion . . . . . . . . . . . . . . . . . . . . . 36 6.2.3 Rolle der Twist-Funktion . . . . . . . . . . . . . . . . . . . . . . 37 7 Vergleich der Generatoren 39 8 Ausblick 41
1 Einleitung 1.1 Motivation Das Zufallsprinzip ist in vielen Bereichen der Informatik essenziell und dennoch ist es von deterministischen Maschinen kaum umsetzbar. Doch insbesondere die IT-Sicherheit macht sich den Zufall für die Verschlüsselung sensibler Daten zu Nutze. Ohne die Einhaltung der Schutzziele der IT-Sicherheit, der Integrität, der Vertraulichkeit und der Authentizität ist keine Internetseite und kein digitales System zu betreiben. Es gibt allein 16,5 Millionen Internetseiten mit der Top-Level-Domain .de, Tendenz steigend [3]. Parallel dazu steigt nach Angaben des Berichts zur Lage der IT-Sicherheit in Deutsch- land 2020 die Menge an Schadsoftware stetig [2]. Um sich gegen diese Angriffe zu rüsten werden Verschlüsselungsmechanismen genormt und bedienen sich an umfassend geprüften Verfahren zur Erzeugung der Schlüssel. In der Regel ist die scheinbare Zufälligkeit der Zufallszahl durch Algorithmen bestimmt. Aus diesem Grund lässt ich der Begriff des Zufalls nicht mehr im Zusammenhang mit den gängigen Verfahren zur Schlüsselerzeugung anwenden. Stattdessen bedarf es einer Abgrenzung zwischen echtem Zufall und der hier vorliegenden Pseudozufälligkeit und einer wissenschaftliche Auseinandersetzung zur Erzeugung von Letzterem. 1.2 Aufbau der Arbeit Zunächst werden einige theoretische Grundlagen erläutert, die später Anwendung finden sollen. Bevor dann Pseudozufallsgeneratoren vorgestellt und analysiert werden, sind Anforderungen aufzustellen, die zur Bewertung herangezogen werden. Geprüft werden diese Anforderungen mittels statistischer Tests, Algorithmen zur Analyse von Bitsequenzen, die von Pseudozufallsgeneratoren erzeugt werden. Die dann vorgestellten Generatoren, der Blum-Micali -Generator und der Mersenne-Twister -Generator müssen diese Tests dann durchlaufen. Dazu wurde ein Tool entwickelt, bei dem sich die Parameter zur Erzeugung der Pseudozufallszahlen einzeln einstellen lassen, um diese dann in statistischen Tests zu untersuchen. Anschließend folgt ein Vergleich beider Generatoren und ein Ausblick darüber, wie man diese Arbeit fortführen könnte. 1
2 Theoretische Grundlagen 2.1 Zufall und Pseudozufall Von Zufall wird laut Definition gesprochen, wenn zwischen zwei Ereignissen kein kausaler Zusammenhang besteht, oder auch, wenn die Einflussfaktoren für ein Ereignis bekannt sind, diese jedoch nicht messen und nur rein statistisch voraussagen kann [10]. Eine weitere Definition aus Complexity and Cryptography zieht die Kolmogorov-Chaitin- Komplexität heran. Diese sagt aus, dass eine Zeichenkette dann zufällig ist, wenn diese nicht durch Algorithmen zu erzeugen ist, die kürzer sind, als die Zeichenkette selbst oder anders formuliert, wenn es keine Komprimierung für diese Zeichenkette gibt [12]. Im Umkehrschluss heißt das, dass jedes einzelne Bit einer Bitsequenz den Informati- onsgehalt dieser Sequenz erweitert. In einer Zeichenkette der Länge k darf das Bit an der Stelle n (mit 1 < n < k) nicht mit der Kenntnis über die Bits {1, ..., n − 1} in probabilistischer Polynomialzeit (kurz P P ) zu berechnen sein, die Entropie muss also maximal sein. Definition 2.1 [11] Die Komplexitätsklasse PP ist die Klasse von Entscheidungs- problemen, die von einer nichtdeterministischen Turing-Maschine, welche auf jeder Entscheidungsstufe zwischen allen Transitionen entsprechend einer Wahrscheinlichkeits- verteilung wählt, in Polynomialzeit mit einer Fehlerrate < 12 gelöst werden können. Dass kein deterministischer Algorithmus echte Zufallszahlen erzeugen kann, wurde bereits angedeutet. Echter Zufall erfordert Input über zusätzliche Hardware, wie über die Tastatur. Dabei können das niederwertigste Bit (LSB) aus der Zeit in Millisekun- den zwischen zwei Tastenanschlägen oder Zufallsbits aus atmosphärischem Rauschen verwendet werden, wie es bei random.org angewandt wird [5]. Mit diesen Methoden Zufallssequenzen für praktische Anwendungen zu erzeugen ist jedoch zu aufwändig und nicht praktikabel, da die Erzeugung von Bitsequenzen mit 128 oder 256 Bits, wie sie unter anderem im AES-Verschlüsselungsverfahren benutzt werden, zu lange dauert. Stattdessen werden Pseudozufallsgeneratoren verwendet, um Pseudozufallszahlen zu berechnen. Pseudozufallsgeneratoren sind deterministische Algorithmen, die eine echt zufällige Bitsequenz der Länge k entgegennehmen und eine pseudozufällige Sequenz der Länge l(k) > l erzeugen. Diese Pseudozufallszahl soll möglichst nah an der oben 2
aufgeführten Definition für echten Zufall sein. Zwar ist zwangsläufig ein kausaler Zusam- menhang zwischen den Bits gegeben, da jedes Bit mit den gleichen Anweisungsschritten des Algorithmus erzeugt wird, es kann jedoch bewerkstelligt werden, dass dieser Zusam- menhang nicht in probabilistischer Polynomialzeit berechenbar ist. 2.2 Pseudozufallsgeneratoren Im Allgemeinen wird ein PP-Algorithmus, der eine Zeichenkette x ∈ {0, 1}k übergeben bekommt und eine Zeichenkette G(x) der Länge l(k) > k produziert, als Pseudozufalls- generator bezeichnet. Der Algorithmus hat aber noch eine Reihe weiterer Bedingungen zu erfüllen, damit dieser als Pseudozufallsgenerator deklariert werden kann. John Tal- bot und Dominic Welsh haben in Complexity and Cryptography einige Bedingungen aufgestellt und bewiesen [16]. Die Wesentlichen werden im Folgenden kurz aufgezeigt. 2.2.1 Prädiktoren Als Gegenspieler zu Pseudozufallsgeneratoren operieren Prädiktoren. Ein Prädiktor P ist ein PP-Algorithmus, der mit möglichst hoher Genauigkeit das nächste Bit der Ausgabe des Pseudozufallsgenerators G(x) unter Angabe des Startwerts x zu berechnen versucht. Schon durch einfaches Raten ist bei zwei den möglichen Werten, die das Bit annehmen kann, die Trefferwahrscheinlichkeit bei etwa 12 . Ist diese jedoch signifikant höher als das so gilt, dass der ein Bitgenerator G kein Pseudozufallsgenerator ist. Der Next-Bit-Test ist ein Algorithmus, der für einen Generator G und einen Prädiktor P prüft, ob P die einzelnen Bits der erzeugten Bitsequenz G(x) richtig berechnen kann. Pseudocode 1 : Next-Bit-Test [16] 1 S e l e c t random x ∈R {0, 1}k and compute G(x) = y1 y2 ...yl(k) . 2 Give t h e p r e d i c t o r P t h e i n p u t 1k . 3 i←1 4 w h i l e i ≤ l(k) 5 P e i t h e r a s k s f o r t h e next b i t , yi , o r o u t p u t s a g u e s s b 6 i f P o u t p u t s a g u e s s then 7 t h e t e s t ends and P p a s s e s t h e t e s t i f f b = yi . 8 else 9 P i s g i v e n t h e next b i t yi 10 i ← i + 1. 11 end−w h i l e 12 P f a i l s s i n c e i t has not made a g u e s s . 3
Für jedes Bit in yi in G(x) gibt P entweder eine Prognose ab oder bekommt das nächste Bit. P besteht, wenn eine richtige Prognose abgegeben wurde und schlägt fehl, wenn keine Prognose abgegeben wurde. Nun kommt die Bewertung, ob G ein Pseudozufallsgenerator ist. Dies ist der Fall genau dann, wenn die Wahrscheinlichkeit, dass P für x ∈R {0, 1} den Next-Bit-Test besteht nicht signifikant größer ist als 12 : P r[P besteht den Next-Bit-Test] ≤ 1 2 + neg(k). Diese Wahrscheinlichkeit ist signifikant größer, wenn deren Differenz zu 1 2 größer ist, als die Funktion neg(k) (engl. negligible). Definition 2.2 [7] Eine Funktion f : N → R heißt vernachlässigbar, wenn diese schneller gegen Null konvergiert, als das Inverse jedes Polynoms. 1 |f (n)| < (2.1) p(n) Welcher Wert der Bestehenswahrscheinlichkeit des Prädiktors P als vernachlässigbar gilt, wird in Abhängigkeit zur Länge k der Eingabe x des Generators G definiert. Je länger der Eingabewert x für G ist, desto geringer fällt der vernachlässigbare Unterschied zu 12 aus. Kann kein Prädiktor P , wie oben definiert, das nächste Bit xi einer Bitsequenz x berechnen, so heißt x unvorhersagbar. 2.2.2 Statistische Tests Mithilfe statistischer Tests wird die Definition von Pseudozufallsgeneratoren weiter verfeinert. Diese dienen dazu, festzustellen, inwieweit sich Bits eines Pseudozufallsgene- rators G von echten Zufallsbits unterscheiden. Definition 2.3 [16] Ein statistischer Test T ist ein PP-Algorithmus, der für einen gegebenen Eingabestring entweder 0 oder 1 zurück gibt. Ein pseudozufälliges Erzeugnis G(x) soll nicht unterscheidbar von echtem Zufall sein. Das heißt, dass die Wahrscheinlichkeit für einen statistischen Test T unter Eingabe eines Pseudozufallswertes G(x) eine 1 ausgibt, sich nicht signifikant von der Wahr- scheinlichkeit, dass unter Eingabe einer echten Zufallszahl y eine 1 ausgegeben wird, unterscheiden darf. |P r[T (G(x)) = 1] − P r[T (y) = 1]| ≤ neg(k). (2.2) Ein Generator G ist genau dann ein Pseudozufallsgenerator, wenn dieser jeden erdenkli- chen statistischen Test besteht. Dies ist jedoch die Schwierigkeit bei der Generierung 4
von Zufall beziehungsweise Pseudozufall durch Algorithmen. Ein PP-Algorithmus G muss konzeptionell so aufgebaut sein, dass dieser jeden Test T besteht und gleichzeitig effizient sein muss, um für reelle Einsatzzwecke, wie der Verschlüsselung, praktikabel zu bleiben. 2.2.3 Einwegfunktionen Für die Erzeugung zufallsähnlicher Werte bedienen sich Pseudozufallsgeneratoren an Einwegfunktionen, die folgendermaßen definiert sind. Definition 2.4 [16] Eine Einwegfunktion f ist eine Funktion, für die es einen Polynomialzeit-Algorithmus gibt, der den Funktionswert y = f (x) mit gegebenem x berechnet, dessen Urbild x unter Kenntnis von y jedoch von keinem PP-Algorithmus berechnet werden kann. Bekannte Einwegfunktionen sind unter anderem die Primfaktorzerlegung oder der diskre- te Logarithmus. Letzterer wird in einem späteren Abschnitt in dieser Arbeit präsentiert, da auf diesem der Blum-Micali-Generator basiert. Die genannten Einwegfunktionen berechnen eine natürliche Zahl. Unter Anwendung eines Hardcore-Prädikats wird aus dieser dann das Pseudozufallsbit berechnet. Ein Prädikat ist im Allgemeinen eine Funktion, die eine beliebig lange Eingabe entgegennimmt und einen Wahrheitswert zurückgibt. Ein Hardcore-Prädikat erweitert diese Definition folgendermaßen: Definition 2.5 [16] Ein Hardcore-Prädikat B : {0, 1}∗ → {0, 1} einer Einwegfunkti- on f ist ein Prädikat, dessen Funktionswert unter Kenntnis von x effizient von ei- nem Polynomialzeit-Algorithmus berechnet werden kann, wohingegen der Funktionswert schwer zu berechnen ist, wenn ausschließlich f(x) bekannt ist. Bei zwei möglichen Ausgabewerten, entweder 0 oder 1, bedeutet das, dass die Ausgabe in je der Hälfte der Fälle 0 oder 1 annehmen kann. |P r[B(x) = 0] − P r[B(x) = 1]| ≤ neg(k). (2.3) Daraus folgt, dass es keinen Prädiktor geben kann, der mit einer signifikant höheren Wahrscheinlichkeit die Ausgabe des Hardcore-Prädikats prognostiziert als 12 . Da bei einer Quelle von echt-zufälligen Bits für jedes ausgegebene Bit die Wahrscheinlichkeit von 12 gegeben ist, dass dieses eine 0 oder eine 1 annimmt, werden auch statistische Tests keinen signifikanten Unterschied zwischen einer generierten Bitsequenz G(x) und einer echt-zufälligen erkennen können. Voraussetzung dafür ist, dass der Generator G die einzelnen Bits unter Anwendung einer Einwegfunktion und einem zugehörigem Hardcore-Prädikat erzeugt. 5
3 Anforderungen an Pseudozufallsgeneratoren Pseudozufallsgeneratoren werden nicht ausschließlich für kryptographische Zwecke benutzt, sondern in den verschiedensten Anwendungen, um unter anderem eine Ent- scheidungsfindung durch den Computer zu simulieren. In einem solchen Kontext sind die Pseudozufallszahlen nicht sicherheitsrelevant, demnach sind auch die Anforderungen geringer. Nichtsdestotrotz sind hier ebenso Erzeugnisse erwünscht, die echtem Zufall möglichst nahe kommen. In Verschlüsselungsverfahren werden Pseudozufallszahlen als Schlüssel verwendet. Um zu vermeiden, dass der Schlüssel bei einem Angriff mit einem effizienteren Algorithmus als Brute-Force bestimmt werden kann, ist es wichtig, dass der Schlüssel jeden Wert der Schlüsselmenge mit etwa der gleichen Wahrscheinlichkeit annehmen kann. Bei einer typischen Schlüssellänge von 2048 Bits heißt das, dass jeder der 22048 Bitkombinationen mit einer Wahrscheinlichkeit von 22048 1 als Schlüssel gewählt wird. 3.1 Effizienz So unterschiedlich, wie die Einsatzzwecke sind, so verschieden streng sind auch die Anforderungen zu formulieren. In jedem Einsatzfall ist jedoch gewünscht, dass der Generator eine Bitsequenz einer beliebigen Länge effizient bestimmen kann. Das bedeutet, dass der Generator die Bitsequenz in polynomieller Laufzeit bestimmen können muss. Definition 3.1 Die Komplexitätsklasse P ist die Klasse der Entscheidungsprobleme, die von einer deterministischen Turing-Maschine in Polynomialzeit gelöst werden können. Die Entscheidungsprobleme der Komplexitätsklasse P gelten als effizient berechenbar. Dass ein Generator ein P-Algorithmus ist, gilt als elementare Voraussetzung dafür, dass dieser praktikabel verwendet werden kann. In dieser Arbeit werden die untersuchten Generatoren einer Laufzeitanalyse unterzogen. Diese besteht aus einer mathematischen Berechnung der Laufzeit aller Algorithmen, die Teil des zu untersuchenden Generators sind, sowie einer Zeitmessung der Laufzeit bei der Berechnung einer Zufallszahl einer bestimmten Länge. 6
3.2 Kryptographische Sicherheit In der Kryptographie gelten für Pseudozufallsgeneratoren noch weitere Anforderungen. Verschiedene Organisationen überarbeiten regelmäßig die Definitionen für einen krypto- graphisch sicheren Pseudozufallsgenerator, darunter das National Institute of Standards and Technology (kurz NIST) [6]. Im folgenden Abschnitt werden diese Anforderungen vorgestellt. 3.2.1 Zufälligkeit Das NIST definiert Zufall wie folgt [6]: A random bit sequence could be interpreted as the result of the flips of an unbiased “fair” coin with sides that are labeled ”0” and ”1”, with each flip having a probability of exactly 12 of producing a ”0” or ”1”. Die Schwierigkeit, diese Eigenschaft durch einen Algorithmus zu erreichen, wurde bereits erläutert. Des Weiteren sind aber auch Methoden beschrieben worden, mit denen Pseudozufall echtem Zufall sehr nahe kommt. Durch das Hardcore-Prädikat einer Einwegfunktion wird die in dem Zitat genannte Verteilung mit vernachlässigbaren Abweichungen erreicht. Untereinander dürfen sich die Bits dabei nicht in der Wahrscheinlichkeit beeinflussen, eine 0 oder eine 1 anzunehmen. Alle Elemente einer Bitsequenz sind somit unabhängig voneinander zu erzeugen. 3.2.2 Unvorhersagbarkeit Kein Prädiktor P sollte ein durch einen Pseudozufallsgenerator G erzeugtes Bit, mit einer signifikant höheren Wahrscheinlichkeit als 12 , unter Kenntnis der von G bisher erzeugten Bits, bestimmen können. Der Einsatz von Einwegfunktionen im Zusammenhang mit Hardcore-Prädikaten ist eine Möglichkeit, um einen Prädiktor, der in probabilistischer Polynomialzeit läuft, bei der Berechnung eines pseudozufälligen Bits zu täuschen. Das impliziert auch, dass der Seed x, mit dem der Generator G den Pseudozufallswert G(x) erzeugt, für jeden Prädiktor P unvorhersagbar sein muss. Ist dies nicht der Fall, ließen sich die folgenden Bits von G(x) unter Anwendung des Algorithmus von G mithilfe des Seeds berechnen. 3.2.3 Blackboxing Aus den ersten beiden Bedingungen folgt, dass zwar das Prinzip, nach dem ein Pseudo- zufallsgenerator G arbeitet, bekannt sein darf, aber der Pseudozufallsgenerator G selbst 7
eine Blackbox sein muss. Die Ausgabe von G darf den inneren Zustand des Generators nicht offenbaren, da durch diesen die zukünftig auszugebenden Bits zu bestimmen sind. Die Sicherheit von G ist nur gewährleistet, wenn der Seed und weitere Parameter geheim gehalten werden. Der Seed ist der einzige Bestandteil eines Pseudozufallsgenerators, der trotz Determinismus die Ausgabe einer pseudozufälligen Bitsequenz ermöglicht, die un- unterscheidbar von echtem Zufall ist. Daher ist ein Seed von einer nichtdeterministischen Quelle zu wählen. 3.2.4 Wahl des Seeds Da ein deterministischer Algorithmus qualitativ hochwertige Pseudozufallszahlen nur mittels echtem Zufall erzeugen kann, steht und fällt die Sicherheit eines Generators mit der Wahl des Seeds [16]. Verschiedene Quellen können dabei in Betracht gezogen werden. Die Nutzung von atmosphärischem Rauschen oder der Zeit, zwischen zwei Tastenanschlägen eines Nutzers, kann dafür verwendet werden. Dabei wird stets das niederwertigste Bit (kurz LSB) verwendet, da bei diesem die Wahrscheinlichkeit in etwa gleich verteilt ist, sodass jeder mögliche Wert angenommen wird. Bei der Nutzung des höchstwertigsten Bits müsste angenommen werden, dass sehr hohe Werte mit einer etwa gleich hohen Wahrscheinlichkeit erreicht werden, wie geringe Werte. Das LSB nimmt abwechselnd eine 0 oder eine 1 an und ist somit die beste Wahl für die Verwendung als Zufallsbit. Der Seed selbst muss zufällig und unvorhersagbar sein, damit der Pseudozufallsgenerator diese Bedingungen auch erfüllen kann. In dieser Arbeit wird die Ausgabe der Generatoren bezüglich der Wahl des Seeds untersucht, wobei die Seeds je nach Experiment von random.org [5] bezogen oder selbst gewählt werden. Dazu ist anzunehmen, dass die Nutzung von Seeds mit geringerem Wert in einer Erzeugung qualitativ geringerer Pseudozufallszahlen resultiert. Diese Hypothese wird auf ihre Richtigkeit überprüft. 8
4 Statistische Tests Die bisher formulierten Anforderungen an Pseudozufallsgeneratoren werden mittels statistischer Tests überprüft. In Kapitel 2.2.2 wurden statistische Tests bereits genauer beschrieben. Statistische Tests sind Algorithmen, die eine Bitsequenz auf Zufälligkeit testen und diese dann als zufällig oder nicht zufällig bewerten [16]. Dies lässt dann auf die Qualität des Generators schließen, der diese Bitsequenz generiert hat. Das NIST hat eine Reihe statistischer Tests entwickelt [6]. Einige davon wurden im Zuge dieser Arbeit implementiert und werden nachfolgend vorgestellt. Vorerst gilt es zu klären, wie diese Tests zu interpretieren sind. Dabei ist zu beachten, dass keine endliche Menge statistischer Tests vollständig sein kann. Daher können statistische Tests das Vorliegen von Zufall nicht beweisen oder widerlegen, sondern indizieren nur, ob eine Bitsequenz als zufällig oder nicht zufällig generiert betrachtet werden kann. Getestet wird mit der Grundannahme, dass die vorliegende Sequenz zufällig ist. Diese Annahme wird als Nullhypothese H0 bezeichnet. Durch statistische Tests wird H0 entweder bewiesen oder widerlegt. Dafür muss im Anschluss des Tests eine statistische Auswertung stattfinden. Um auf die Richtigkeit von H0 zu prüfen, wird ein kritischer Wert t bestimmt, der als Schwelle dient, ab der H0 akzeptiert oder abgelehnt wird. Unter Anwendung des Tests wird dann für eine Bitsequenz ein Statistikwert S bestimmt, der dann mit t verglichen wird, um den p-W ert auszurechnen. Der p-W ert ist die Wahrscheinlichkeit, dass ein perfekter Zufallsgenerator eine Sequenz ausgibt, die weniger zufällig ist, als die Getestete. Ein p-W ert von 1 lässt somit auf per- fekten Zufall schließen und ein p-W ert von 0 auf völlige Unzufälligkeit. Schließlich wird dieser p-W ert gegen das Signifikanzniveau α geprüft, das angibt, welche Wahrschein- lichkeit der p-W ert unterschreiten muss, damit die Nullhypothese für eine Bitsequenz verworfen wird. Da das NIST sich an den für α üblichen Wert von 0,01 gehalten hat [6], wird dieser Wert auch in dieser Arbeit als Signifikanzniveau herangezogen. Jeder vorgestellte Test besteht also aus zwei Bestandteilen. Zum einen bestehen diese aus den Algorithmen zur Bestimmung des Statistikwertes. Die Algorithmen zu den Tests werden in dieser Arbeit präsentiert. Zum anderen folgt darauf zur Bestimmung des p-W ertes die statistische Auswertung. Sämtliche Berechnungen werden somit auf die Ausgabe eines Wahrheitswertes geführt, der die Annahme von H0 , dass Zufall vorliegt, bestätigt oder verwirft, wie es in Kapitel 2.2.2 beschrieben wird. 9
Jeder Test gibt ein Tupel aus zwei Werten zurück. Der erste Wert ist der Statistikwert, der zur graphischen Darstellung verwendet wird. Der zweite Wert ist das Resultat der Auswertung, der p-W ert, nach dem H0 angenommen oder verworfen wird. Die Formel zur Berechnung des p-W ertes wird im Anschluss an den Algorithmus zu jedem Test präsentiert. Dabei wird je Test die Gaußsche Fehlerfunktion [1] verwendet, die wie folgt definiert ist: Z ∞ 2 2 erf c(z) = √ e−u du. (4.1) n z 4.1 Frequency (Monobit) Test Der Frequency Test, auch Monobit Test genannt, dient dazu das Verhältnis zwischen der Anzahl der Nullen und der Einsen zu bestimmen [6]. Algorithmus 2 : Frequency (Monobit) Test [6] 1 def f r e q u e n c y _ t e s t ( s e q u e n c e ) : 2 z e r o = s e q u e n c e . count ( ’ 0 ’ ) 3 one = s e q u e n c e . count ( ’ 1 ’ ) 4 return z e r o / len ( s e q u e n c e ) , f r e q u e n c y _ s t a t i s t i c ( z e r o , one ) Das Verhältnis zwischen der Anzahl der Nullen und der Länge wird graphisch dargestellt und ist der erste Rückgabewert in Zeile 4. Die Anzahl der Nullen und Einsen wird zuvor bestimmt, um sie der Statistikfunktion zu übergeben. Darin wird der p-W ert für eine Bitsequenz der Länge n mit einer Anzahl von x0 Nullen und x1 Einsen wie folgt bestimmt: 1. Berechnung von Sn mit Sn = x1 − x0 , wobei x0 der Variable zero (Zeile 2) und x1 der Variable one (Zeile 3) entspricht. |Sn | 2. Berechnung von sobs = √ . n 3. Schließlich folgt die Berechnung des p-W ertes: sobs p-W ert = erf c √ . (4.2) n Wenn p-W ert ≥ α gilt, wird angenommen, dass die getestete Bitsequenz nach dem Frequency Test zufällig ist. Wie oben erwähnt, wird für α der Wert 0,01 verwendet. Nach der Formel ist für den p-W ert anzunehmen, dass im Verhältnis hohe Differenzen zwischen Einsen und Nullen zur Verwerfung der Nullhypothese führen. Für belastbare Ergebnisse wird empfohlen, dass für diesen Test Bitsequenzen von mindestens 100 Bits verwendet werden. 10
4.2 Runs Test Der Runs Test zählt die Anzahl der ununterbrochenen Folgen identischer Bits. Dabei ist jede Folge vorher und hinterher von entgegengesetzten Bits umgeben [6]. Algorithmus 3 : Runs Test [6] 1 def r u n s _ t e s t ( s e q u e n c e ) : 2 total_runs = 1 3 for elem in range ( 1 , len ( s e q u e n c e ) ) : 4 i f s e q u e n c e [ elem ] != s e q u e n c e [ elem − 1 ] : 5 t o t a l _ r u n s += 1 6 return t o t a l _ r u n s , r u n s _ s t a t i s t i c ( s e q u e n c e ) Zur Bestimmung des Statistikwertes Vn (obs) wird beginnend beim zweiten Bit über die Sequenz iteriert (Zeile 3) und der Zähler total_runs jedes Mal inkrementiert, wenn sich das aktuelle Bit vom vorigen unterscheidet und somit eine neue Folge anfängt. Der Zähler total_runs wird direkt mit 1 initialisiert (Zeile 2), da das erste Bit den Anfang der ersten Folge darstellt, was durch die Schleife nicht festgestellt werden würde. Nun wird der p-W ert bestimmt: 1. Um den Runs Test durchzuführen, gilt das Bestehen des Frequency Tests als Voraussetzung. Daher wird zuvor das Verhältnis π der Einsen zur Länge der Sequenz bestimmt. Sei n die Länge der Sequenz und x1 die Anzahl der Einsen in ebendieser Sequenz: π = xni . 2. Sei τ = π2 . Wenn |π − 12 | ≥ τ gilt, ist der Frequency Test nicht bestanden. Der Runs Test kann nun einem p-W ert von 0,0000 abgebrochen werden. Ansonsten wird mit Schritt drei fortgefahren. 3. Nun wird der p-W ert berechnet. Dazu wird der Statistikwert Vn (obs) aus dem oben beschriebenen Algorithmus herangezogen. Die Formel lautet wie folgt: |Vn (obs) − 2nπ(1 − π)| p-W ert = erf c √ . (4.3) 2 2nπ(1 − π) Auch hier gilt bei einem p-W ert ≥ 0, 01, dass H0 für diese Sequenz akzeptiert wird. Beispiel 3.1 Sei y = 10010 11001 mit n = 10 die zu untersuchende Sequenz. Dann gilt π = 10 5 = 12 < √2n = τ und der Frequeny Test somit als bestanden. Die Menge der Folgen lautet {1; 00; 1; 0; 11; 00; 1} und enthält sieben Elemente, so ist Vn (obs) = 7. Die 11
Sequenz y wird als zufällig angenommen, da sich folgender p-W ert ergibt: ! |7 − 2 ∗ 10 ∗ 21 ∗ (1 − 12 )| p-W ert = erf c √ = 0.2059 ≥ 0, 01. (4.4) 2 2 ∗ 10 ∗ 12 ∗ (1 − 12 ) 4.3 Test for the Longest Run of Ones in a Block In diesem Test wird die zu testende Bitsequenz in M -Bit große Blöcke eingeteilt und in diesen die längste ununterbrochene Folge von Einsen bestimmt. Es wird geprüft, ob die Länge dieser Folge mit der erwarteten Länge der längsten Folge von Einsen einer zufälligen Bitsequenz übereinstimmt [6]. Außer der zu testenden Sequenz gibt noch einige weitere Übergabeparameter. Diese Übergabeparameter hängen von der Länge n der Sequenz ab und sind auf folgende Weise zu wählen: • M Die Länge M der gleich großen Blöcke ist abhängig von der Gesamtlänge n der Sequenz. Im Algorithmus 4 wird m anstelle von M verwendet. Minimum n M 128 8 6272 128 750.000 10.000 Tabelle 4.1: Länge M der Blöcke • vi Die Längen der längsten in einem Block festgestellte Folgen werden in Klassen eingeteilt. Dabei orientieren sich die Klassen an der Blockgröße M . Die Frequenz vi entspricht der Häufigkeit, dass die längste in einem Block gefundene Folge der Länge der zugehörigen Klasse entspricht. Gegeben sind diese Klassen im Algorithmus durch die Liste v_values. vi M =8 M = 128 M = 10.000 v0 ≤1 ≤4 ≤ 10 v1 2 5 11 v2 3 6 12 v3 ≥4 7 13 v4 8 14 v5 ≥9 15 v6 ≥ 16 Tabelle 4.2: Einteilung der Frequenzen vi in Klassen 12
• πi Zu jede dieser Klassen vi gibt es eine Wahrscheinlichkeit πi , dass die längste Folge eines Blockes die Länge hat, die dieser Klasse zugeordnet sind. Diese Wahrscheinlichkeiten πi sind vorgegeben und entsprechen dem Übergabe- parameter pi_values aus dem Algorithmus. Der Übergabeparameter k gibt die Anzahl der Klassen, der verschiedenen zu messenden Frequenzen an. • K Der Parameter K, dem Algorithmus als k übergeben, ist vorgegeben und hängt von M ab. Algorithmus 4 : Test for the Longest Run of Ones in a Block [6] 1 def l on ge s t_ on e s_ r un _t e st ( sequence , k , m, v_values , p i _ v a l u e s ) : 2 # i n i t i a l i z e loop parameters 3 block_count = int ( len ( s e q u e n c e ) / m) 4 start = 0 5 end = m 6 # l i s t t o c o un t runs f o r e v e r y l e n g t h i n v _ v a l u e s 7 f r e q u e n c i e s = [ 0 f o r _ in range ( k + 1 ) ] 8 # go o v e r e v e r y b l o c k 9 f o r _ in range ( block_count ) : 10 b l o c k = s e q u e n c e [ s t a r t : end ] 11 max_run = 0 12 curr_run = 0 13 # co un t l o n g e s t run i n c u r r e n t b l o c k 14 f o r b i t in b l o c k : 15 i f b i t == ’ 1 ’ : 16 curr_run += 1 17 max_run = max( max_run , curr_run ) 18 else : 19 max_run = max( max_run , curr_run ) 20 curr_run = 0 21 max( max_run , curr_run ) 22 # compare w i t h NIST g i v e n v_value c l a s s e s 23 i f max_run < v_values [ 0 ] : 24 f r e q u e n c i e s [ 0 ] += 1 25 f o r j in range ( k ) : 26 i f max_run == v_values [ j ] : 27 f r e q u e n c i e s [ j ] += 1 28 i f max_run > v_values [ k − 1 ] : 29 f r e q u e n c i e s [ k ] += 1 30 s t a r t += m # g e t n e x t b l o c k 31 end += m 32 s t a t i s t i c = longest_ones_run_statistic ( frequencies , 33 block_count , pi_values , k ) 34 return v_values , f r e q u e n c i e s , s t a t i s t i c 13
Der Algorithmus arbeitet wie folgt: 1. Es wird eine Liste mit Nullen initialisiert, in denen die Häufigkeit der Frequenzen gezählt wird (Zeile 7). start und end (Zeile 3 und 4) sind die Grenzen des aktuell zu prüfenden Blockes. 2. In der ersten Schleife (Zeile 9) wird über die Blöcke iteriert, in der zweiten Schleife (Zeile 14) über die Bits des jeweiligen Blockes, um die längste Folge von Einsen dieses Blockes zu bestimmen. 3. Anschließend (Zeile 23 bis 29) wird die längste Folge des Blockes der jeweiligen Klasse zugeordnet. Mit dem Ende der ersten Schleife sind somit die Frequenzen der Klassen bekannt und im Anschluss werden die Statistiken berechnet. Mit den gesammelten Frequenzen lässt sich der p-W ert berechnen: 1. χ2 (obs) gibt an, wie groß die Übereinstimmung der festgestellten Frequenzen mit den erwarteten Frequenzen ist. In der Berechnung entspricht N der Anzahl der M -Bit Blöcke: K X (vi − N πi )2 2 χ (obs) = . (4.5) i=0 N πi 2. Schließlich lässt sich der p-W ert berechnen: K χ2 (obs) p-W ert = igamc , . (4.6) 2 2 Die igamc()-Funktion stammt aus Handbook of Applied Mathematical Functions [1] und wird auch als unvollständige Gammafunktion bezeichnet. Diese bekommt zwei Werte übergeben. Die Definition sieht folgendermaßen aus: Z ∞ γ(a, x) 1 P (a, x) ≡ ≡ e−t ta−1 dt. (4.7) Γ(a) Γ(a) x Für diesen Test ist eine Länge n der zu testenden Sequenz von mindestens 128 Bits erforderlich. 4.4 Cumulative Sums Test Die kumulative Summe einer Bitsequenz der Länge n ist ein Random Walk mit der Länge n, bei dem sich ein Wert xi der kumulativen Summe mit 1 ≤ i ≤ n aus der Summe über alle Bits bj mit 1 ≤ j ≤ i berechnen lässt. Zur Normierung der kumulativen Summe wird mit (-1, +1) anstelle von (0, 1) gerechnet [6]. 14
Algorithmus 5 : Cumulative Sums Test [6] 1 def cumulative_sum_test ( s e q u e n c e ) : 2 c o u n t s = [ 0 f o r _ in range ( len ( s e q u e n c e ) ) ] 3 for i n d e x in range ( len ( s e q u e n c e ) ) : 4 sub = 1 5 i f s e q u e n c e [ i n d e x ] == ’ 0 ’ : 6 sub = −1 7 i f index > 0 : 8 c o u n t s [ i n d e x ] = c o u n t s [ i n d e x − 1 ] + sub 9 else : 10 c o u n t s [ i n d e x ] = sub 11 s t a t i s t i c = c u s u m _ s t a t i s t i c ( len ( s e q u e n c e ) , a r r a y ( c o u n t s ) ) 12 return counts , s t a t i s t i c Zu Anfang wird eine Liste mit der Länge n, also der Länge der Sequenz, mit Nullen initialisiert (Zeile 2). Anschließend wird in der Schleife (Zeile 3) über die Sequenz iteriert und das entsprechende Element der kumulativen Summe gebildet. sub gibt für den Bitwert an der Stelle i an, ob mit -1 oder mit +1 gerechnet werden muss (Zeile 4). Die Schleife endet mit der Fallunterscheidung zur Prüfung, ob i = 0 gilt (Zeile 7) und der Zeiger demzufolge auf das erste Bit zeigt. Dann erhält das erste Feld der kumulativen Summe den Wert von sub (Zeile 10). Ansonsten muss der Wert von sub auf den Wert des vorigen Feldes addiert werden, sodass die Summe aller bisherigen Elemente einbezogen wird. Mit dem resultierenden Feld S lässt sich der p-W ert berechnen: 1. Zunächst ist das Maximum z = max1≤k≤n |Sk | der Partialsummen S zu bestimmen. 2. Der p-W ert ergibt sich aus der Gleichung: ( nzX −1)/4 " ! # (4k + 1)z (4k − 1)z p-W ert = 1 − Φ p −Φ √ + −n (n n k=( +1)/4 (4.8) z ( nzX −1)/4 " ! # (4k + 3)z (4k + 1)z Φ p −Φ √ . (n n k=( −n z −3)/4 Die Standardnormalverteilung Φ ist gegeben durch [6]: Z z 1 2 /2 Φ(z) = √ e−u du. (4.9) 2π −∞ 15
Auch für diesen Test wird eine Bitsequenz mit mindestens 100 Bits empfohlen. Die ge- testete Sequenz kann als zufällig angenommen werden, wenn ein p-W ert ≥ 0, 01 erreicht wird. Bei einer zufälligen Sequenz ist zu erwarten, dass unter den kumulativen Summem keine großen Exkursionen von der x-Achse zu sehen sind [6]. Große Maximalwerte deuten auf eine lange Folge von Nullen oder Einsen hin, woraufhin die Nullhypothese H0 mit einer geringeren Wahrscheinlichkeit akzeptiert wird. Aber auch bei zu geringen Werten wird H0 verdächtig, denn diese deuten auf eine zu gleiche Verteilung der Nullen und Einsen hin. 4.5 Weitere Tests Außer den genannten, vom NIST stammenden, statistischen Tests wurden zwei weitere entwickelt. Diese dienen jedoch nur als erste Orientierungspunkte, damit sich der Beob- achter ein vorläufiges Bild machen kann, ob für gegebene Sequenzen die Nullhypothese H0 , dass diese Sequenzen als zufällig angenommen werden können, zutrifft. Zu diesen Tests gibt es folglich keine statistische Auswertung. Durch deren graphische Darstellung können jedoch die Ergebnisse weiterer durchgeführter Test, wie der beschriebenen, erahnt werden. Mit dem Longest Run in the Sequence Test ist zu erkennen, wie lang die längste Folge der gesamten Sequenz ist. Zu geringe oder zu hohe Werte lassen auf eine große Gleich- verteilung oder eine große Ungleichverteilung schließen. Dieser Test ist eine Ergänzung zum Test for the Longest Run of Ones in a Block, da so auch Folgen erkannt werden können, die länger sind als ein Block. Der Distribution of Zeroes Test gibt für k Sequenzen an, wie groß in diesen Sequenzen die Wahrscheinlichkeit ist, dass das Bit an der Stelle i den Wert Null hat. Daraus kann schlussgefolgert werden, ob ein Generator Regelmäßigkeiten bei der Generierung der Bitsequenzen aufweist. Trotz aller Tests bleibt immer die Gefahr, das eine nicht zufällige Zeichenkette als zufällig angenommen wird, da jede endliche Menge statistischer Tests um Tests erweiter- bar ist, die die bisher gesammelten Informationen ergänzen. Auch das NIST hat noch einige weitere Tests entwickelt [6]. In dieser Arbeit werden zur Bewertung der folgenden Generatoren die beschriebenen statistischen Tests herangezogen. 16
5 Blum-Micali-Generator Der Blum-Micali -Generator wurde im Jahr 1984 von seinen Namensgebern Manuel Blum und Silvio Micali vorgestellt und gilt als kryptographisch sicherer Pseudozufalls- generator [8]. Bevor dieser These auf den Grund gegangen wird, muss das Konzept des Generators beleuchtet werden. 5.1 Konzept Dazu wird der Pseudocode des Generators betrachtet. Pseudocode 6 : Blum-Micali-Generator - Aufbau [16] 1 Choose a random k−b i t prime p and a p r i m i t i v e r o o t g mod p . 2 Choose x ∈R Z∗p . 3 Let x1 = x and xi = g xi−1 mod p , f o r i = 2 t o l(k) . 4 Let bi = most(xi ) . 5 Output t h e s e q u e n c e bl(k) , bl(k)−1 , ..., b2 , b1 . Zunächst werden die Parameter für den Algorithmus gewählt (Zeile 1 und 2). Es gibt drei Parameter: • Eine echt zufällige Primzahl p mit einer Länge von k Bits. • Eine zu p zugehörige Primitivwurzel g mod p. • Ein echt zufälliger Seed x. Eine Zahl a ∈ Z ist eine Primitivwurzel mod m, wenn sich alle Elemente der primen Restklassengruppe mod m als Potenzen ai mit 1 ≤ i < a darstellen lassen [9]. Beispiel 5.1 Die 3 ist eine Primitivwurzel mod 5, da jedes Element x mit 1 ≤ x < 5 der Restklassengruppe mod 5 als Potenz 3i mit 1 ≤ i < 5 zu erzeugen ist. 31 ≡ 3 mod 5 32 ≡ 1 mod 5 33 ≡ 4 mod 5 34 ≡ 2 mod 5 Tabelle 5.1: Restklassengruppe mod 5. 17
Nun wird die Berechnung der Pseudozufallszahl b mit einer Länge von l(k) ≥ k Bits betrachtet: 1. Für jedes i in 2 ≤ i ≤ l(k)... a) ...wird xi = g xi−1 mod p berechnet, wobei zuvor x1 := x definiert wird (Zeile 3). b) ...ist das Bit bi = most(xi ) unter Anwendung des Hardcore-Prädikats most zu berechnen (Zeile 4). 2. Die Bits werden dann im umgekehrter Reihenfolge ausgegeben (Zeile 5). Kern des Algorithmus Das zentrale Element des Blum-Micali -Generators ist die diskrete Exponentialfunktion dexp(p, g, x) = (p, g, g x mod p). (5.1) Die Umkehrfunktion zur diskreten Exponentialfunktion mod p ist der diskrete Loga- rithmus mod p. Da es keinen deterministischen Algorithmus gibt, der den diskreten Logarithmus mod p in Polynomialzeit berechnet, gilt die dexp-Funktion als Einweg- funktion. Als zugehöriges Hardcore-Prädikat wird die Berechnung des höchstwertigen Bits verwendet, um ein einzelnes Bit der Pseudozufallszahl zu bestimmen [16]. 0, if x < (p − 1)/2, most(x) = (5.2) 1, sonst. Die Bedeutung dieser beiden Funktionen für die Produktion von Pseudozufall wurde in Kapitel 2.2 bereits aufgeführt. In der Theorie gilt die Kombination aus Einwegfunktion und Hardcore-Prädikat als sicher gegenüber jedem Prädiktor. In letzter Instanz hängt die Sicherheit aber noch von den Parametern ab. Um die Ausgabe dieses Pseudozufallsgenerators bezüglich der Parameter zu untersuchen, gegebenenfalls Pattern festzustellen und somit die Schwächen zu bestimmen, ist eine Implementierung des Generators notwendig. Aus diesem Grund werden fortführend die Bestandteile des Algorithmus vorgestellt und Unterschiede zwischen dem bereits präsentierten Pseudocode und der reellen Implementierung aufgezeigt. Sämtliche Implementierungen werden mittels Python vorgenommen. Da die Effizienz eine wichtige Anforderung an Pseudozufallsgeneratoren ist, wird eine Laufzeitabschätzung von jedem Algorithmus durchgeführt. 18
5.2 Implementierung 5.2.1 Diskrete Exponentialfunktion Zunächst wird kurz die diskrete Exponentialfunktion betrachtet. Diese Funktion ist ein Zweizeiler, wobei die Laufzeit von x abhängt. Zur Berechnung von g x wird die Funktion pow(g, x) verwendet. Algorithmus 7 : diskrete Exponentialfunktion 1 def dexp ( p , g , x ) : 2 return pow( g , x ) % p Die pow(g, x)-Funktion ließe sich auch ohne Verwendung der Standardbibliothek umsetzen: return pow( g , x ) \% p → g_x = g f o r _ in range ( 1 , x ) : g_x = g_x ∗ g return g_x % p Durch Betrachtung der Variante mit der for-Schleife wird die Laufzeit des Algorithmus klar. Das x als Zählervariable gibt die Laufzeit an, welche offenbar mit steigendem x linear ansteigt. Die restlichen Operationen sind mathematischer Natur mit konstanter Laufzeit und beeinflussen die Laufzeit somit nicht wesentlich. Da der lineare Anstieg durch x der steilste ist, ist der Algorithmus der Laufzeitklasse O(x) zuzuordnen. Definition 5.1 [14] Sind f (n) und g(n) Funktionen N → R≥0 , so sagt man: f (n) ist O(g(n)) oder f (n) ∈ O(g(n)) oder „f (n) wächst höchstens in der Größen- ordnung von g(n)” genau dann, wenn es Konstanten c > 0 und n0 ≥ 0 gibt, so dass f (n) ≤ c ∗ g(n) für alle n ≥ n0 gilt. 5.2.2 Hardcore-Prädikat Das Hardcore-Prädikat ist der zweite wichtige Baustein des Blum-Micali-Generators, aber ebenso kurz, wie die Einwegfunktion. Algorithmus 8 : Hardcore-Prädikat 1 def most ( x , p ) : 2 return 0 i f x < ( p − 1 ) / 2 e l s e 1 Zurückgegeben wird 0 oder 1, je nachdem, ob die Bedingung x < (p − 1)/2 für die Ausgabe von 0 zutrifft oder nicht. Die Laufzeit für das Prüfen dieser Bedingung verhält sich unabhängig von den Übergabeparametern x und p, was auf eine konstante Laufzeit 19
schließen lässt. Damit ist dieser Algorithmus der Klasse O(1) zuzuordnen. Die einzige Besonderheit des Algorithmus ist, dass dieser zusätzlich zu x auch die Primzahl p übergeben bekommt. Dies wird der Funktion in der Definition als bekannt vorausgesetzt. In der Implementierung ist das nicht der Fall. 5.2.3 Der Generator Die Implementierung des Blum-Micali -Generators selbst unterscheidet sich leicht von dem gegebenen Pseudocode. Algorithmus 9 : Blum-Micali-Generator 1 def blum_micali_generator ( p , g , random , l k ) : 2 r e s u l t = "" 3 for i in range ( 1 , l k ) : 4 r e s u l t = s t r ( u t i l s . most ( random , p ) ) + r e s u l t 5 random = u t i l s . dexp ( p , g , random ) 6 r e s u l t = s t r ( u t i l s . most ( random , p ) ) + r e s u l t 7 return r e s u l t Anstatt die Wahl der Parameter p, g und des Seeds random, der x aus dem Pseudocode entspricht, innerhalb des Generators vorzunehmen, werden diese übergeben. Damit ist der Generator keine Blackbox mehr und es besteht ein erhöhtes Risiko, dass ein Angreifer die Daten zur Generierung der Pseudozufallszahl abfangen und die Berechnungen auch selbst vornehmen kann. Beim Einsatz in der Kryptographie ist das eine kritische Sicher- heitslücke. In diesem Falle wird es vernachlässigt, da es zu experimentellen Zwecken dient, die Parameter selbst bestimmen zu können. Die Ausdrücke in der Schleife (Zeile 4 und 5) sind verglichen mit dem Pseudocode in umgekehrter Reihenfolge. Zuerst wird die Funktion most(random,p) aufgerufen und das Ergebnis vor den bisherigen result-String vorangestellt. Anschließend wird die Berech- nung von dexp(p,g,random) vorgenommen. Hintergrund ist, dass im Pseudocode auch von dem Seed x most(x) berechnet werden soll. Das muss geschehen, bevor x, also im im- plementierten Python-Algorithmus random, mit dem Ergebnis von dexp(p,g,random) überschrieben wird. Entsprechend muss vor Abschluss des Algorithmus für das letzte Ergebnis der Exponentialfunktion most(random,p) aufgerufen werden (Zeile 6). In den Algorithmen wird mit Stringrepräsentationen der Bitsequenzen gearbeitet. Die Laufzeit des Generators als Ganzes wird hauptsächlich von random und von der erwünschten Länge lk der Ausgabe bestimmt. Wird der Aufruf von dexp(p,g,random) außer Acht gelassen, ergibt sich eine in Abhängigkeit von lk lineare Laufzeit. Die Lauf- zeit von dexp(p,g,random) hängt von random ab, also von einem Wert, der sich nach 20
jedem Durchlauf der Schleife verändert. Wie groß dieser Wert werden kann, ist wiederum abhängig von p, aufgrund der Modulo-Funktion innerhalb von dexp(p,g,random). Das erschwert eine Laufzeitberechnung. Da jedoch der Exponent random der Exponential- funktion durch die Modulo-Operation gedeckelt wird, bleibt es für dexp(p,g,random) über alle Durchgänge bei einer linearen Laufzeit. Durch diese Kombination aus Algorithmen mit linearen Laufzeiten ist zu schließen, dass der Generator in Polynomialzeit läuft. 5.3 Hilfsfunktionen Zur Berechnung der möglichen Primitivwurzeln zu einer Primzahl werden weitere Hilfsfunktionen benötigt. Die Funktion zur Prüfung, ob zwei Zahlen teilerfremd sind, wird benötigt, um die Liste der Primitivwurzeln zu einer Primzahl zu bestimmen. 5.3.1 Teilerfremdheit Zwei Zahlen a, b ∈ N heißen teilerfremd, wenn es kein x ∈ N mit x > 1 gibt, sodass gilt: a mod x = b mod x = 0. (5.3) Gesucht wird also der größte gemeinsame Teiler (ggT) beider Zahlen. ggT (a, b) gibt die größte natürliche Zahl x an, der a, b ∈ N restlos teilt. Algorithmus 10 : Prüfen auf Teilerfremdheit 1 def c o p r i m e _ i n t e g e r s ( a , b ) : 2 i f a == b : 3 return F a l s e 4 lower = a i f a < b else b 5 f o r i in range ( 2 , l o w e r +1): 6 i f a % i == 0 and b % i == 0 : 7 return F a l s e 8 return True Der Algorithmus prüft zunächst, ob a und b identisch sind und bricht die Berechnung infolgedessen ab (Zeile 2 und 3), da die beiden Zahlen in diesem Fall nicht teilerfremd sein können. Anschließend wird der kleinere der beiden Werte ausgemacht (Zeile 4), weil dieser Wert die Obergrenze für einen größten gemeinsamen Teiler ist. Für jeden Wert zwischen zwei und dem niedrigeren der beiden Zahlen wird überprüft, ob dieser Wert beide Zahlen restlos teilt (Zeile 5 und 6). Ist dies der Fall wird abgebrochen. Wird kein gemeinsamer Teiler gefunden, wird True zurückgegeben, womit die beiden Zahlen 21
teilerfremd sind. Mit einer Schleife, deren Laufzeit linear zur Größe des kleinsten Wertes ist und weiteren Operationen in konstanter Laufzeit, wächst die Laufzeit des ganzen Algorithmus in linearer Größenordnung bezüglich a und b. 5.3.2 Primitivwurzeln Nun wird die Berechnung aller Primitivwurzeln mod p zu einer Primzahl p betrachtet. Algorithmus 11 : Primitivwurzeln bestimmen 1 def g e t _ p r i m i t i v e _ r o o t ( p ) : 2 coprimes = [ ] 3 for i in range ( 1 , p ) : 4 i f coprime_ints ( i , p ) : 5 c o p r i m e s . append ( i ) 6 k = 0 7 while k < len ( c o p r i m e s ) : 8 list = [] 9 f o r i in range ( 1 , p ) : 10 c a l c = pow( c o p r i m e s [ k ] , i ) % p 11 i f c a l c not in l i s t : 12 l i s t . append ( c a l c ) 13 else : 14 c o p r i m e s . remove ( c o p r i m e s [ k ] ) 15 k = k − 1 16 break 17 k = k + 1 18 return c o p r i m e s Dazu wird zunächst für alle Zahlen 1 ≤ i < p überprüft, ob diese teilerfremd zu p ist. Jedes i, dass diese Bedingung erfüllt, wird in der Liste coprimes gespeichert (Zeile 2 bis 5). Über diese Liste coprimes wird iteriert und für jeden Wert k geprüft, ob sich alle Elemente der primen Restklassengruppe mod p als Potenz k i mit 1 ≤ i < p darstel- len lassen (Zeile 9 und 10). Die Potenzen zu jedem Wert werden in der Liste list gespeichert (Zeile 10 bis 12). Wiederholt sich ein Wert in list bevor alle Elemente der Restklassengruppe gefunden wurden, dann ist k keine Primitivwurzel mod p, wird aus list entfernt und es wird mit dem nächsten Element von coprimes fortgefahren (Zeile 13 bis 16). Die verbliebene Liste coprimes entspricht der Menge der Primitiv- wurzeln mod p. 22
Diese Brute-Force-Methode hat eine polynomielle Laufzeit. Die Größenordnung dieser Laufzeit ergibt sich durch die Verschachtelung aus der while-Schleife, die über die Liste der zu p teilerfremden Elemente iteriert (Zeile 7) und der for-Schleife, die für jedes Element dieser Liste prüft, ob sich alle Werte der Restklassengruppe mod p als Potenz berechnen lassen (Zeile 9). Die pow-Funktion innerhalb dieser Verschachtelung ermittelt die Potenzen (Zeile 10) und erhöht die Laufzeit pro Durchgang der for-Schleife noch einmal um den Faktor i. Durch diese Verschachtelung ergibt sich eine polynomielle Laufzeit in Abhängigkeit von p. 5.4 Untersuchung Nachfolgend werden Statistiken gezeigt, die verdeutlichen, welche Bedingungen für die Parameter gelten müssen, damit die resultierende Pseudozufallszahl echtem Zufall möglichst nahe kommt. Die p-W erte der vorgestellten Statistikfunktionen dienen als Richtwert für die Auswertung. Dazu werden jeweils Bitsequenzen mit einer Länge von 128 Bits verwendet. Aus der Betrachtung der beiden fundamentalen Bestandteile des Blum-Micali -Generators, der diskreten Exponentialfunktion und dessen Hardcore- Prädikat, lassen sich bereits einige Hypothesen ableiten. 5.4.1 Patternerzeugung in Abhängigkeit der Primzahl p Es ist schnell festzustellen, dass eine gute Wahl des Parameters p von großer Bedeutung ist. Denn mit p wird durch die Verwendung des Modulo ein Maximalwert für das Ergebnis der diskreten Exponentialfunktion festgelegt. Abhängig von der Größe von p wiederholen sich damit auch die generierten Bits. Die Periode kann dabei eine Maximallänge von p erreichen, ist jedoch häufig kürzer. Für die Nutzung dieses Generators in der Kryptographie bedeutet das, dass p vorzugsweise einen höheren Wert als die Länge l(k) der benötigten Bitsequenz haben sollte. Wenn ein Prädiktor P bei einer Periodenlänge von m Bits Kenntnis über alle Bits einer Periode hat, dann kann dieser alle folgenden Bits berechnen, sofern das Pattern erkannt wird. Besonders gut sind diese Pattern unter Betrachtung einer Auswertung des Cumulative Sums Test zu erkennen, wie sich in der folgenden Grafik zeigt. Exemplarisch ist für die grün dargestellte Sequenz die Entwicklung einer Periode durch ein rotes Rechteck markiert. Jeder Punkt gibt die Entwicklung der kumulativen Summen wieder. Für die grüne Sequenz ergibt sich ein Bitpattern mit einer Periodenlänge m = 22. Da ein ansteigender Trend vorliegt, besteht diese Sequenz zur Mehrheit aus Einsen. An dem durchgehenden Gefälle am Ende jeder Periode ist zu erkennen, dass die Sequenz aber auch längere Teilfolgen von Nullen enthält. 23
Abbildung 5.1: Mustererkennung am Beispiel der kumulativen Summen mit p = 23, x = 10 und g ∈ {17; 19; 20}. 5.4.2 Der Seed x gibt den Startwert des Patterns vor Es wird eine Reihe unterschiedlicher Bitsequenzen mit konstanten Parametern p und g und mit 1 ≤ x ≤ 200, so ist auch zwischen den Sequenzen ein repetitives Muster so erkennen. Für die Bitsequenzen wird eine Länge von 32 Bits gewählt. Abbildung 5.2: Anteil an Nullen bei p = 23, g = 5 und x ∈ [1, 100] pro Sequenz. Der prozentuale Anteil der Nullen (Frequency Test) ist aufgetragen über x ∈ [1, 100] und zeigt, dass sich für ein p und ein g mit 100 unterschiedlichen Werten für x 100 Bitsequenzen erzeugen lassen, wobei sich innerhalb eines bestimmten Intervalls von x der Anteil an Nullen in den Sequenzen wiederholt. Werden diese Bitsequenzen geprüft, ist zu erkennen, dass es sich bei den generierten 24
Pseudozufallszahlen mit etwa dem gleichen Anteil an Nullen, um annähernd dieselben Bitfolgen handelt. Der entscheidende Unterschied ist, dass diese Sequenzen ungleich anfangen, jedoch in den gleichen Pattern münden. Seien u und v zwei mit diesem Generator generierte Bitsequenzen, bei denen die Ergebnisse der Funktion dexp(p, g, x) zur Berechnung der Bits von u und v periodisch sind und dem gleichen Pattern entsprechen, dann lässt sich v als Rotation von u darstellen und umgekehrt. Eine Rotation ist eine Verschiebung der Bits einer Sequenz um n Stellen, sodass bei einer Rotation nach links die n höchstwertigen Bits die n niederwertigsten Stellen einnehmen. Bei einer Rechtsrotation gilt dies entsprechend umgekehrt. Diese Phänomen wird nachfolgend am Beispiel zweier Sequenzen u und v gezeigt. Dafür wird mit p = 17 ein niedriger Wert gewählt, damit sich möglichst früh eine Wiederholung des Patterns zeigt, dass durch die Ergebnisse von dexp(p, g, x) zustande kommt. Auch g = 6 ist fest für beide Sequenzen fest. Der Seed für u ist mit x0 = 5 und für v mit x0 = 11 bestimmt. Durchlauf u mit x0 = 5 v mit x0 = 11 i dexp(17, 6, xi ) most(xi ) dexp(17, 6, xi ) most(xi ) 0 5 0 11 1 1 7 0 5 0 2 14 1 7 0 3 9 1 14 1 4 11 1 9 1 5 5 0 11 1 6 7 0 5 0 7 14 1 7 0 ... ... ... Tabelle 5.2: Patternentstehung bei festen p = 17 und g = 5. Es ist zu beachten, dass der Blum-Micali -Generator die Bits in umgekehrter Reihenfolge ausgibt. Die Bitsequenzen lauten also: u = ...10 01110 0 v = ...0 01110 01 Nach fünf Durchläufen wiederholen sich somit die Werte von dexp(17, 6, xi ) für u und v. Das heißt, das Pattern hat eine Periodenlänge von m = 5. Wenn p und g den oben angegebenen Werten entsprechen, werden immer Bitsequenzen mit dem Pattern 01110 erzeugt, wenn Wert für x als Seed aus der Menge {7; 14; 9; 11; 5} gewählt wird. 5.4.3 Die Menge möglicher Pattern ist durch g gegeben Auch die Primitivwurzel g mod p hängt mit der Patternerzeugung zusammen. Das ist durch folgendes Experiment feststellbar. 25
Es werden verschiedene Mengen M von Bitsequenzen erstellt. Es wird eine feste Primzahl p gewählt, mit der alle Bitsequenzen über alle Mengen generiert werden. Für jede dieser Mengen Mi wird eine feste Primitivwurzel g mod p bestimmt, mit der alle Sequenzen dieser Menge berechnet werden, jedoch für jede Menge Mi eine andere Primitivwurzel. Jede dieser Mengen Mi besteht aus 100 Bitsequenzen, mit x ∈ [1, 100]. Wie in Abbildung 5.2 zu erkennen war, zeigt sich an dem Anteil der Nullen in den Sequenzen, welche Werte der Seed x haben muss, damit sich die gleichen Pattern erzeugt werden. Wenn für unterschiedliche Primitivwurzeln g mod p die gleichen Pattern generiert werden würden, dann sähen auch die Graphen für die Frequenz der Nullen in den Sequenzen über x ∈ [1, 100] gleich aus oder wiesen höchstens eine vertikale Verschiebung um ein bestimmtes x auf. Durchgeführt wird dieses Experiment mit den Mengen Mi mit 1 ≤ i ≤ 4, deren je 100 Bitsequenzen mit folgenden Parametern generiert werden: M1 : p = 23, g = 7, x ∈ [1, 100] M2 : p = 23, g = 10, x ∈ [1, 100] M3 : p = 23, g = 11, x ∈ [1, 100] M4 : p = 23, g = 14, x ∈ [1, 100] In den nächsten Grafiken ist für jede Menge Mi die Frequenz der Nullen über x aufgetragen. Dabei steht hinter jedem x eine Sequenz, die mit x als Seed ge- neriert wurde, bei gleich bleibenden Werten für p und g, wie oben angegeben. Abbildung 5.3: Anteil an Nullen über Abbildung 5.4: Anteil an Nullen über x für M1 . x für M2 . 26
Abbildung 5.5: Anteil an Nullen über Abbildung 5.6: Anteil an Nullen über x für M3 . x für M4 . Alle generierten Sequenzen haben eine Länge von 32 Bits. Dadurch, dass p gering be- stimmt ist, kann ein schnell wiederkehrendes Muster erkannt werden. Dass die Graphen gänzlich unterschiedlich sind, ist eine hinreichende Bedingung dafür, dass durch die Wahl von g bei festem p unterschiedliche Mengen von Pattern vorgegeben werden. Durch die Wahl von x wird dann aus dieser Menge von Pattern eines ausgewählt. Zu beachten ist, dass andersherum die Gleichheit der Muster der Graphen jedoch nicht hinreichend wäre, um zu beweisen, dass mit unterschiedlichen Primitivwurzeln g mod p die gleichen Pattern erzeugt werden können. Das ist wichtig, da verschiedene Sequenzen den gleichen Anteil an Nullen haben können, ohne aus denselben, wiederkehrenden Pattern zu bestehen. Somit ist es möglich, dass sich zwei Graphen mit dem Anteil der Nullen über x ähneln, obwohl die Sequenzen, die hinter jedem x stehen, gänzlich unterschiedlich sind. 5.4.4 Niedrige Seeds x fallen aus dem Muster Unter Betrachtung der Graphen fallen noch weitere Eigenschaften in den Mengen M auf. Bisher wurde zum einen gezeigt, dass innerhalb der Bitsequenzen Pattern festgestellt werden können. Zum anderen wurde aufgeführt, dass diese Pattern nicht nur innerhalb der Sequenzen zu finden sind, sondern auch über mehrere Sequenzen hinweg, wenn feste p und g für alle Sequenzen gewählt werden. Bestehen zwei Sequenzen u und v aus dem gleichen Pattern, ist die eine Sequenz als Rotation der Anderen darzustellen. Ferner erweist aber auch, dass u = v mit xu als Seed von u und xv als Seed von v für eine bestimmte Differenz |xv − xu | gilt. Es werden somit in immer gleichen Abständen |xv − xu | die exakt gleichen Sequenzen genieriert. Für die Parameter der Mengen Mi mit 1 ≤ i ≤ 4 zeigt sich, dass diese Differenz |xv − xu | = p − 1 in Abhängigkeit von p steht. Hintergrund ist die Eigenschaft von Primitivwurzeln g mod p, dass das Ergebnis jeder 27
Sie können auch lesen