Lassen Sie uns etwas Computer-Poker spielen, nur Sie, mich und einen Server, dem wir beide vertrauen. Der Server verwendet einen Pseudo-Zufallszahlengenerator, der unmittelbar vor dem Spielen mit einem 32-Bit-Startwert initialisiert wird. Es gibt also etwa vier Milliarden mögliche Decks.
Ich habe fünf Karten in der Hand - anscheinend spielen wir nicht Texas Hold 'Em. Angenommen, die Karten werden mir zugeteilt, eine zu Ihnen, eine zu mir, eine zu Ihnen und so weiter. Ich habe also die erste, dritte, fünfte, siebte und neunte Karte im Stapel.
Früher habe ich den Pseudo-Zufallszahlengenerator vier Milliarden Mal einmal mit jedem Samen ausgeführt und die erste Karte, die für jeden erzeugt wurde, in eine Datenbank geschrieben. Angenommen, meine erste Karte ist die Pik-Dame. Dies zeigt nur eine als erste Karte in jedem 52 dieser möglichen Decks. Daher haben wir die möglichen Decks von vier Milliarden auf etwa 80 Millionen reduziert.
Angenommen, meine zweite Karte ist die drei Herzen. Jetzt führe ich meinen RNG noch 80 Millionen Mal aus und benutze die 80 Millionen Samen, die als erste Nummer die Pikdame produzieren. Das dauert ein paar Sekunden. Ich schreibe alle Kartensätze auf, die die drei Herzen als dritte Karte erzeugen - die zweite Karte in meiner Hand. Das sind wiederum nur etwa 2% der Decks, jetzt sind wir nur noch 2 Millionen Decks.
Angenommen, die dritte Karte in meiner Hand ist die 7 der Vereine. Ich habe eine Datenbank mit 2 Millionen Samen, die meine zwei Karten verteilen. Ich führe meine RNG noch 2 Millionen Mal aus, um die 2% der Decks zu finden, die die 7 der Schläger als dritte Karte produzieren, und wir haben nur noch 40.000 Decks.
Sie sehen, wie das geht. Ich renne meine RNG 40000-mal mehr, um alle Samen zu finden, die meine vierte Karte produzieren, und das bringt uns auf 800 Decks, und dann noch 800 Mal, um die ~ 20 Samen zu bekommen, die meine fünfte Karte produzieren, und jetzt habe ich gerade Diese zwanzig Kartenstapel generieren und ich weiß, dass Sie eine von zwanzig möglichen Händen haben. Außerdem habe ich eine sehr gute Vorstellung davon, was ich als nächstes zeichnen werde.
Verstehst du jetzt, warum wahre Zufälligkeit wichtig ist? So wie Sie es beschreiben, denken Sie, dass die Verteilung wichtig ist, aber die Verteilung macht einen Prozess nicht zufällig. Unvorhersehbarkeit macht einen Prozess zufällig.
AKTUALISIEREN
Basierend auf den (jetzt aufgrund ihrer unkonstruktiven Natur gestrichenen) Kommentaren sind mindestens 0,3% der Menschen, die dies gelesen haben, verwirrt, was meinen Standpunkt angeht. Wenn Menschen gegen Punkte argumentieren habe ich nicht gemacht, oder noch schlimmer, argumentiert für Punkte, die ich habe auf der Annahme, dass ich sie nicht gemacht habe, dann weiß ich, dass ich mehr klar und sorgfältig erklären muß.
Es scheint eine besondere Verwirrung in Bezug auf die Wortverteilung zu geben , daher möchte ich die Verwendung sorgfältig nennen.
Die Fragen sind:
- Wie unterscheiden sich Pseudozufallszahlen und echte Zufallszahlen?
- Warum ist der Unterschied wichtig?
- Haben die Unterschiede etwas mit der Verteilung der Ausgabe des PRNG zu tun?
Beginnen wir mit dem perfekten Weg, ein beliebiges Kartenspiel zu generieren, mit dem man Poker spielen kann. Dann werden wir sehen, wie sich andere Techniken zum Erzeugen von Decks unterscheiden, und ob es möglich ist, diesen Unterschied zu nutzen.
Beginnen wir mit der Annahme, dass wir eine magische Box haben TRNG
. Als Eingabe geben wir ihm eine ganze Zahl n, die größer oder gleich eins ist, und gibt als Ausgabe eine wirklich zufällige Zahl zwischen eins und n einschließlich an. Die Ausgabe der Box ist völlig unvorhersehbar (wenn eine andere Zahl als eine gegeben wird) und jede Zahl zwischen eins und n ist so wahrscheinlich wie eine andere; das heißt, die Verteilung ist einheitlich . (Es gibt andere fortgeschrittene statistische Überprüfungen der Zufälligkeit, die wir durchführen könnten; ich ignoriere diesen Punkt, da dies für meine Argumentation nicht von Belang ist.
Wir beginnen mit einem ungemischten Kartenspiel. Wir bitten die Box um eine Zahl zwischen eins und 52 - das heißt TRNG(52)
. Welche Zahl auch immer zurückgegeben wird, wir zählen so viele Karten aus unserem sortierten Stapel ab und entfernen diese Karte. Es wird die erste Karte im gemischten Deck. Dann fragen wir nach TRNG(51)
und tun das Gleiche, um die zweite Karte auszuwählen und so weiter.
Ein anderer Blickwinkel ist: Es gibt 52! = 52 x 51 x 50 ... x 2 x 1 mögliche Decks, was ungefähr 2 226 entspricht . Wir haben einen von ihnen zufällig ausgewählt.
Jetzt geben wir die Karten aus. Wenn ich mir meine Karten anschaue, habe ich keine Ahnung, welche Karten Sie haben. (Abgesehen von der offensichtlichen Tatsache, dass Sie keine der Karten haben, die ich besitze.) Dies könnten beliebige Karten sein, mit gleicher Wahrscheinlichkeit.
Lassen Sie mich also sicherstellen, dass ich das klar erkläre. Wir haben eine gleichmäßige Verteilung jedes einzelnen Outputs von TRNG(n)
; Jeder wählt mit der Wahrscheinlichkeit 1 / n eine Zahl zwischen 1 und n aus. Das Ergebnis dieses Prozesses ist, dass wir eine von 52 ausgewählt haben! möglich Decks mit einer Wahrscheinlichkeit von 1/52 !, so die Verteilung über die Menge der möglichen Decks sind auch einheitlich.
Gut.
Nehmen wir an, wir haben eine weniger magische Box, die mit einem Label versehen ist PRNG
. Bevor Sie es verwenden können, müssen sie werden ausgesät mit einem 32 - Bit - Zahl ohne Vorzeichen.
ASIDE: Warum 32 ? Könnte es nicht mit einer 64-, 256- oder 10000-Bit-Zahl gesetzt werden? Sicher. Aber (1) in der Praxis werden die meisten handelsüblichen PRNGs mit einer 32-Bit-Zahl ausgesät, und (2) wenn Sie 10000 zufällige Bits haben, um den Samen zu erstellen, warum verwenden Sie dann überhaupt einen PRNG? Sie haben bereits eine Zufallsquelle von 10000 Bits!
Wie auch immer, zurück zur Funktionsweise des PRNG: Nachdem es ausgesät wurde, können Sie es auf dieselbe Weise verwenden, wie Sie es verwenden TRNG
. Das heißt, Sie übergeben eine Zahl n, und Sie erhalten eine Zahl zwischen 1 und n einschließlich. Darüber hinaus ist die Verteilung dieser Leistung mehr oder weniger einheitlich . Das heißt, wenn wir PRNG
nach einer Zahl zwischen 1 und 6 fragen, erhalten wir 1, 2, 3, 4, 5 oder 6 in etwa einem Sechstel der Zeit, unabhängig davon, was der Samen war.
Ich möchte diesen Punkt mehrmals betonen, weil es scheint, dass einige Kommentatoren verwirrt werden. Die Verteilung des PRNG ist auf mindestens zwei Arten einheitlich. Angenommen, wir wählen einen bestimmten Samen aus. Wir würden erwarten, dass die Sequenz PRNG(6), PRNG(6), PRNG(6)...
eine Million Mal zu einer einheitlichen Verteilung der Zahlen zwischen 1 und 6 führen würde. Und zweitens würden wir, wenn wir eine Million verschiedene Samen auswählen und PRNG(6)
einmal für jeden Samen aufrufen, eine gleichmäßige Verteilung der Zahlen von 1 bis 6 erwarten 6. Die Einheitlichkeit des PRNG über eine dieser Operationen ist für den von mir beschriebenen Angriff nicht relevant .
Es wird gesagt, dass dieser Prozess pseudo-zufällig ist, da das Verhalten der Box tatsächlich vollständig deterministisch ist. Es wählt aus 2 32 möglichen Verhaltensweisen, die auf dem Samen basieren. Das heißt, sobald es ausgesät wurde, PRNG(6), PRNG(6), PRNG(6), ...
wird eine Folge von Zahlen mit einer gleichmäßigen Verteilung erzeugt, die jedoch vollständig vom Samen bestimmt wird. Für eine bestimmte Folge von Anrufen, beispielsweise PRNG (52), PRNG (51) ... und so weiter, gibt es nur 2 32 mögliche Folgen. Der Samen wählt im Wesentlichen den, den wir bekommen.
Um ein Deck zu generieren, generiert der Server jetzt einen Startwert. (Wie? Wir kommen zu diesem Punkt zurück.) Dann rufen sie PRNG(52)
an PRNG(51)
und so weiter, um das Deck zu generieren, ähnlich wie zuvor.
Dieses System ist anfällig für den von mir beschriebenen Angriff. Um den Server anzugreifen, säen wir vorab unsere eigene Kopie der Box mit 0 und bitten PRNG(52)
und notieren diese. Dann keimen wir wieder mit 1, fragen nach PRNG(52)
und schreiben das auf bis zu 2 32 -1.
Nun muss der Pokerserver, der PRNG zum Generieren von Decks verwendet, irgendwie einen Samen generieren. Es ist egal, wie sie das tun. Sie könnten anrufen TRNG(2^32)
, um einen wirklich zufälligen Samen zu erhalten. Oder sie könnten die gegenwärtige Zeit als Samen nehmen, was kaum zufällig ist; Ich weiß wie viel Uhr es ist. Der Punkt meines Angriffs ist, dass es keine Rolle spielt, weil ich meine Datenbank habe . Wenn ich meine erste Karte sehe, kann ich 98% der möglichen Samen entfernen. Wenn ich meine zweite Karte sehe, kann ich 98% mehr eliminieren und so weiter, bis ich schließlich eine Handvoll möglicher Samen finden kann und mit hoher Wahrscheinlichkeit weiß, was in Ihrer Hand liegt.
Nun möchte ich noch einmal betonen, dass hier davon ausgegangen wird, dass wirPRNG(6)
, wenn wir eine Million Mal anrufen würden, jede Zahl ungefähr ein Sechstel der Zeit erhalten würden . Diese Verteilung ist (mehr oder weniger) einheitlich, und wenn Sie sich nur für die Einheitlichkeit dieser Verteilung interessieren, ist das in Ordnung. Die Frage der Frage war, ob es andere Dinge gibt, die sich um die Verteilung von PRNG(6)
uns kümmern. und die Antwort lautet ja . Wir kümmern uns auch um Unvorhersehbarkeit .
Eine andere Möglichkeit, das Problem zu betrachten, besteht darin, dass die Verteilung von einer Million Anrufen zwar in PRNG(6)
Ordnung sein kann, da der PRNG jedoch nur 2 32 mögliche Verhaltensweisen auswählt, nicht jedes mögliche Deck erzeugen kann. Es kann nur 2 32 der 2 226 möglichen Decks erzeugen ; ein winziger Bruchteil. Die Verteilung über alle Decks hinweg ist also sehr schlecht. Der fundamentale Angriff basiert jedoch darauf, dass wir das vergangene und zukünftige Verhalten von einer kleinen Stichprobe seiner Leistung erfolgreich vorhersagen könnenPRNG
.
Lassen Sie mich dies ein drittes oder vier Mal sagen, um sicherzustellen, dass dies einbricht. Hier gibt es drei Distributionen. Zunächst die Verteilung des Prozesses, der den zufälligen 32-Bit-Startwert erzeugt. Das kann völlig zufällig, unvorhersehbar und einheitlich sein und der Angriff wird trotzdem funktionieren . Zweitens, die Verteilung von einer Million Anrufe nach PRNG(6)
. Das kann vollkommen gleichförmig sein und der Angriff wird noch funktionieren. Drittens die Verteilung der Decks, die durch den Pseudozufallsprozess ausgewählt wurde, den ich beschrieben habe. Diese Verteilung ist extrem schlecht; Möglicherweise kann nur ein winziger Bruchteil der möglichen IRL-Decks ausgewählt werden. Der Angriff hängt von der Vorhersagbarkeit des Verhaltens des PRNG ab, basierend auf der teilweisen Kenntnis seiner Ausgabe .
ASIDE: Dieser Angriff setzt voraus, dass der Angreifer den genauen Algorithmus des PRNG kennt oder erraten kann. Ob das realistisch ist oder nicht, ist eine offene Frage. Allerdings, wenn ein Sicherheitssystem entwerfen Sie entwerfen müssen sie sicher vor Angriffen sein, auch wenn der Angreifer alle Algorithmen im Programm kennt . Anders ausgedrückt: Der Teil eines Sicherheitssystems, der für die Sicherheit des Systems geheim bleiben muss, wird als "Schlüssel" bezeichnet. Wenn Ihr System für die Sicherheit von den verwendeten Algorithmen als geheim abhängt, enthält Ihr Schlüssel diese Algorithmen . Das ist eine extrem schwache Position!
Weitermachen
Nehmen wir an, wir haben eine dritte beschriftete Box CPRNG
. Es ist eine Krypto-Version von PRNG
. Es ist ein 256-Bit-Startwert und kein 32-Bit-Startwert erforderlich. Es teilt mit PRNG
der Eigenschaft, die das Saatgut aus 2 256 möglichen Verhaltensweisen auswählt . Und wie unsere anderen Maschinen hat es die Eigenschaft, dass eine große Anzahl von Aufrufen CPRNG(n)
eine einheitliche Ergebnisverteilung zwischen 1 und n erzeugt: Jede 1 / n der Zeit passiert. Können wir unseren Angriff dagegen ausführen?
Unser ursprünglicher Angriff erfordert, dass wir 2 32 Zuordnungen von Samen zu speichern PRNG(52)
. Aber 2 256 ist eine viel größere Zahl. Es ist völlig unmöglich CPRNG(52)
, so viele Male auszuführen und die Ergebnisse zu speichern.
Aber nehmen wir an, es gibt einen anderen Weg, um den Wert von CPRNG(52)
Saatgut zu ermitteln und daraus eine Tatsache abzuleiten. Wir waren bisher ziemlich dumm und haben alle möglichen Kombinationen brutal erzwungen. Können wir in die magische Box hineinschauen, herausfinden, wie es funktioniert, und anhand der Ausgabe Fakten über den Samen ableiten?
Nein . Die Details sind zu kompliziert zu erklären, aber CPRNGs sind geschickt so konstruiert, dass es unmöglich ist, abzuleiten, jede nützliche Tatsache über die Samen aus dem ersten Ausgang CPRNG(52)
oder von jeder Teilmenge des Ausgangs, egal wie groß .
OK, also nehmen wir an, der Server verwendet CPRNG
, um Decks zu generieren. Es braucht einen 256-Bit-Startwert. Wie wählt es diesen Samen? Wenn ein Wert ausgewählt wird, den ein Angreifer vorhersagen kann, wird der Angriff plötzlich wieder funktionsfähig . Wenn wir feststellen können, dass von den 2 256 möglichen Startwerten wahrscheinlich nur vier Milliarden vom Server ausgewählt werden, sind wir wieder im Geschäft . Wir können diesen Angriff erneut durchführen, wobei wir nur auf die geringe Anzahl von Samen achten, die möglich ist.
Der Server sollte daher dafür sorgen, dass die 256-Bit-Zahl gleichmäßig verteilt ist, dh jeder mögliche Startwert wird mit einer Wahrscheinlichkeit von 1/2 256 gewählt . Grundsätzlich sollte der Server anrufen TRNG(2^256)-1
, um den Seed für zu erzeugen CPRNG
.
Was ist, wenn ich den Server hacken und hineinschauen kann, um zu sehen, welcher Samen ausgewählt wurde? In diesem Fall kennt der Angreifer die vollständige Vergangenheit und Zukunft des CPRNG . Der Autor des Servers muss sich vor diesem Angriff schützen! (Natürlich, wenn ich diesen Angriff erfolgreich bestreiten kann, kann ich das Geld wahrscheinlich auch direkt auf mein Bankkonto überweisen, daher ist das vielleicht nicht so interessant.) Punkt ist: Der Samen muss ein schwer zu erratendes Geheimnis sein, und ein wirklich zufällige 256-Bit-Zahl ist ziemlich schwer zu erraten.)
Um zu meinem früheren Punkt über Tiefenverteidigung zurückzukommen: Der 256-Bit-Startwert ist der Schlüssel zu diesem Sicherheitssystem. Die Idee eines CPRNG ist, dass das System sicher ist, solange der Schlüssel sicher ist . Selbst wenn jede andere Tatsache über den Algorithmus bekannt ist, sind die Karten des Gegners nicht vorhersagbar, solange Sie den Schlüssel geheim halten können.
Okay, der Samen sollte sowohl geheim als auch gleichmäßig verteilt sein, denn wenn dies nicht der Fall ist, können wir einen Angriff starten. Wir gehen davon aus, dass die Verteilung der Outputs von CPRNG(n)
einheitlich ist. Wie sieht es mit der Verteilung aller möglichen Decks aus?
Man könnte sagen: Es gibt 2 256 mögliche Sequenzen, die vom CPRNG ausgegeben werden, aber es gibt nur 2 226 mögliche Decks. Daher gibt es mehr mögliche Sequenzen als Decks, also geht es uns gut. Jedes mögliche-IRL-Deck ist jetzt (mit hoher Wahrscheinlichkeit) in diesem System möglich. Und das ist ein gutes Argument außer ...
2 226 ist nur eine Annäherung von 52 !. Teilen Sie es aus. 2 256/52 ! kann unmöglich eine ganze Zahl sein, weil zum einen 52! ist durch 3 teilbar aber keine Zweierpotenz ist! Da dies jetzt keine ganze Zahl ist, haben wir die Situation, dass alle Decks möglich sind, aber einige Decks sind wahrscheinlicher als andere .
Wenn dies nicht klar ist, betrachten Sie die Situation mit kleineren Zahlen. Nehmen wir an, wir haben drei Karten, A, B und C. Nehmen wir an, wir verwenden ein PRNG mit einem 8-Bit-Samen, also gibt es 256 mögliche Samen. Es gibt 256 mögliche Ausgaben von PRNG(3)
je nach Seed; Es gibt keine Möglichkeit, dass ein Drittel von ihnen A ist, ein Drittel von ihnen B und ein Drittel von ihnen C, weil 256 nicht gleichmäßig durch 3 teilbar ist.
Ebenso teilt sich 52 nicht gleichmäßig in 2 256 auf, so dass bei der ersten gewählten Karte einige Karten und bei anderen Karten eine Abweichung vorhanden sein muss.
In unserem ursprünglichen System mit einem 32-Bit-Saatgut gab es eine massive Neigung, und die große Mehrheit der möglichen Decks wurde nie produziert. In diesem System können alle Decks hergestellt werden, die Verteilung der Decks ist jedoch immer noch fehlerhaft . Einige Decks sind etwas wahrscheinlicher als andere.
Jetzt ist die Frage: Haben wir einen Angriff, der auf diesem Fehler basiert? und die Antwort ist in der Praxis wahrscheinlich nicht . CPRNGs sind so konzipiert, dass, wenn der Samen wirklich zufällig ist, es rechnerisch unmöglich ist, den Unterschied zwischen CPRNG
und zu erkennen TRNG
.
OK, also zusammenfassend.
Wie unterscheiden sich Pseudozufallszahlen und echte Zufallszahlen?
Sie unterscheiden sich in der Vorhersagbarkeit.
- Wirklich zufällige Zahlen sind nicht vorhersehbar.
- Alle Pseudozufallszahlen sind vorhersagbar, wenn der Samen bestimmt oder erraten werden kann.
Warum ist der Unterschied wichtig?
Denn es gibt Anwendungen, bei denen die Sicherheit des Systems von Unvorhersehbarkeit abhängt .
- Wenn ein TRNG zur Auswahl jeder Karte verwendet wird, ist das System nicht verfügbar.
- Wenn eine CPRNG zur Auswahl jeder Karte verwendet wird, ist das System sicher, wenn der Startwert sowohl unvorhersehbar als auch unbekannt ist.
- Wenn ein gewöhnlicher PRNG mit einem kleinen Saatplatz verwendet wird, ist das System nicht sicher, unabhängig davon, ob der Saatgut unvorhersehbar oder unbekannt ist. ein ausreichend kleiner Saatraum ist anfällig für brutale Angriffe der von mir beschriebenen Art.
Hat der Unterschied etwas mit der Verteilung der Ausgabe des PRNG zu tun?
Die Gleichmäßigkeit der Verteilung oder deren Fehlen für einzelne Anrufe zu RNG(n)
ist nicht relevant für die Angriffe ich beschrieben habe.
Wie wir gesehen haben, erzeugen sowohl a PRNG
als CPRNG
auch arme Distibutionen der Wahrscheinlichkeit, ein einzelnes Deck aller möglichen Decks zu wählen. Das PRNG
ist wesentlich schlechter, aber beide haben Probleme.
Noch eine Frage:
Wenn TRNG so viel besser ist als CPRNG, was wiederum viel besser als PRNG ist, warum werden dann CPRNG oder PRNG verwendet?
Zwei Gründe.
Erstens: Aufwand. TRNG ist teuer . Es ist schwierig, wirklich zufällige Zahlen zu erzeugen. CPRNGs liefern gute Ergebnisse für beliebig viele Anrufe mit nur einem Aufruf von TRNG für den Seed. Der Nachteil ist natürlich, dass Sie diesen Samen geheim halten müssen .
Zweitens: Manchmal wollen wir Vorhersehbarkeit und alles, was uns wichtig ist, ist eine gute Verteilung. Wenn Sie "zufällige" Daten als Programmeingaben für eine Testsuite generieren und ein Fehler angezeigt wird, wäre es schön, wenn Sie die Testsuite erneut ausführen, um den Fehler erneut zu erzeugen.
Ich hoffe das ist jetzt viel klarer.
Wenn Ihnen dies gefallen hat, können Sie sich über das Thema Zufälligkeit und Permutationen informieren.
- Angenommen, ich habe Zufallsdaten gleichmäßig verteilt. Wie kann ich es in eine bestimmte ungleichmäßige Verteilung umwandeln?
- Warum werden einige GUIDs zufällig generiert? Sind alle ihre Bits zufällig? (Nein.) Kann ich mich auf eine GUID als Quelle wahrer Zufälligkeit verlassen? (Nein!)
- Wie kann ich mithilfe der faktoradischen Notation große Zufallszahlen generieren?
- Wie können wir den hier beschriebenen Angriff gegen die zufällige Permutation durchführen?
- Wie viel Voreingenommenheit wird durch die Implementierung der Resttechnik eingeführt
RNG(n)
?