Zufallszahlengenerator
Erzeugen Sie kryptografisch zufällige Zahlen in beliebigen Bereichen.
Eine kurze Geschichte des Computer-Zufalls
Computer sind deterministische Maschinen, was „Zufall“ zu einer seltsamen Sache macht, die sie produzieren sollen. Die Geschichte der Pseudozufallszahlengeneratoren (PRNG) auf Computern beginnt mit John von Neumanns Mittelquadrat-Methode im Jahr 1946, also: die vorherige Zahl quadrieren, die mittleren Ziffern als neuen Wert nehmen, wiederholen. Von Neumann selbst nannte es „einen sündigen Zustand“, Zufallszahlengeneratoren irgendeiner Art zu nutzen, ohne sie vollständig zu verstehen, weil das Mittelquadrat offensichtliche Versagensmodi hat (zykliert auf Null, kurze Perioden). Lehmers linearer Kongruenzgenerator (LCG, 1951), x_(n+1) = (a × x_n + c) mod m, war die erste PRNG-Familie mit vernünftigen statistischen Eigenschaften; das rand() der C-Standardbibliothek nutzt typischerweise immer noch eine LCG-Variante. Der Mersenne Twister (Matsumoto und Nishimura, 1997-1998) lieferte uns einen Generator mit einer Periode von 219937−1 (ja, eine 6.000-stellige Zahl) und exzellenten statistischen Eigenschaften; er wurde der Standard in Python, R, MATLAB, PHP und vielen anderen Sprachen. Marsaglias xorshift-Familie (2003) ist deutlich schneller und klein genug, um in ein Hardware-Register zu passen; das moderne V8 (die JavaScript-Engine von Chrome) nutzt eine xorshift128+-Variante für Math.random(). PCG (Permuted Congruential Generator) von Melissa O'Neill (2014) ist der aktuelle statistische Stand der Technik bei nicht-kryptografischen PRNGs und kombiniert LCG-artige Zustandsfortschreibung mit Ausgabepermutation für exzellente statistische Eigenschaften zu geringen Kosten.
Kryptografisch sichere PRNGs (CSPRNGs) sind eine andere Sache. Definierende Eigenschaft: selbst wenn ein Angreifer jede Ausgabe kennt, die der Generator produziert hat, kann er die nächste Ausgabe nicht mit besserem als vernachlässigbarem Vorteil vorhersagen. Linux' getrandom()-Syscall (im Kernel 3.17, Oktober 2014, hinzugefügt) und das zugrundeliegende /dev/urandom nutzen einen ChaCha20-basierten Generator, gespeist von Hardware-Entropiequellen (RDRAND, Interrupt-Timing, Audio-Rauschen). Windows' BCryptGenRandom nutzt eine AES-CTR-DRBG-Konstruktion (NIST SP 800-90A), gespeist aus mehreren Entropiequellen. macOS / iOS nutzen die arc4random-Familie, ursprünglich ein RC4-basierter CSPRNG, um 2013 auf ChaCha20 umgeschrieben. Der Unterschied zwischen PRNG und CSPRNG zählt enorm: ein PRNG taugt für Spielzufall, A/B-Test-Bucketing oder Simulationen; für alles, was ein Angreifer vorherzusagen versuchen könnte (Sitzungs-Tokens, Passwort-Erzeugung, Sicherheits-IDs), ist nur ein CSPRNG sicher.
JavaScripts zwei Zufalls-APIs
Math.random() ist die ältere, einfachere API, sie liefert eine Fließkommazahl, ungefähr gleichmäßig verteilt in [0, 1). Die ECMAScript-Spezifikation lässt den zugrundeliegenden Algorithmus bewusst unspezifiziert („approximately uniform distribution between 0 and 1, exclusive“), und Engines haben über die Jahre hinweg gewechselt. V8 (Chrome) nutzte viele Jahre einen Multiply-with-Carry-Generator (MWC1616), dann erfolgte 2015 der Wechsel zu xorshift128+ für bessere statistische Eigenschaften. SpiderMonkey (Firefox) und JavaScriptCore (Safari) nutzen ähnliche schnelle nicht-kryptografische Generatoren. Math.random() ist schnell und gleichmäßig genug für Spielmechanik, Simulationen und jede Anwendung, in der Unvorhersehbarkeit keine Sicherheitsanforderung ist. Es ist nicht kryptografisch sicher, die Periode ist implementierungsabhängig, der Zustand kann aus wenigen Ausgaben rekonstruiert werden, und die Sequenz ist nicht sicher für Passwort-Erzeugung oder sicherheitsrelevante Anwendungen. crypto.getRandomValues() ist der CSPRNG der Web Crypto API. Er füllt ein typisiertes Array mit kryptografisch sicheren Zufalls-Bytes, die aus dem CSPRNG des Betriebssystems gezogen werden (dieselbe Quelle, die TLS für Sitzungsschlüssel nutzt). In allen modernen Browsern seit etwa 2014 verfügbar; die maximale Puffergröße in einem einzelnen Aufruf beträgt 65.536 Bytes. Die richtige Wahl für jede Zufallszahl, die zählt, Token-Erzeugung, Sicherheits-IDs, Passwort-Erzeugung, alles, was ein Angreifer vorherzusagen versuchen könnte.
Die Modulo-Bias-Falle
Aus einem CSPRNG einen gleichverteilten Integer in einem bestimmten Bereich zu erzeugen, ist schwieriger, als es aussieht. Der naive Ansatz, crypto.getRandomValues(new Uint8Array(1))[0] % 6 für einen Würfelwurf, produziert eine verzerrte Verteilung, weil 256 nicht gleichmäßig durch 6 teilbar ist. Die Werte 0-3 treten je 43-mal im Bereich 0-255 auf; die Werte 4-5 treten 42-mal auf. Der Bias ist klein bei kleinen Bereichen, aber real und in langen Läufen detektierbar. Der Standardfix ist Rejection Sampling: ein zufälliges Byte erzeugen, prüfen, ob es in das größte Vielfache des Bereichs fällt, das hineinpasst (hier 252 = 42 × 6), nutzen wenn ja, verwerfen und neu versuchen wenn nein. Die Verwurfsrate ist beschränkt durch (Bereich / nächste Zweierpotenz), für „1-6“ verschwendest du also rund 1,5 % der Bytes; für „1-1000000“ gegen einen 32-Bit-Zufalls-Int rund 0,02 %. Jede ernsthafte Zufallsbibliothek implementiert Rejection Sampling; das auf Math.random() basierende Math.floor(Math.random() * (max - min + 1)) + min umgeht den Bias, weil die Präzision von Math.random() hoch genug ist (53 Bit Mantisse), so dass der Bias unter menschlich detektierbaren Schwellen für jeden vernünftigen Bereich liegt. Dieser Generator nutzt CSPRNG-Ausgabe mit Rejection Sampling, gleichmäßige Ausgabe über jeden gewünschten Integer-Bereich.
Anwendungsfälle und welches Niveau an Zufall jeder braucht
- Lotterie- und Verlosungsziehungen. Für nicht-monetäre Ziehungen (Bürotausch, Hackathon-Teamzuweisung, Sitzplan im Klassenzimmer) reicht
Math.random(). Für monetäre Ziehungen oder alles Regulierte einen CSPRNG nutzen und idealerweise die Saat veröffentlichen, damit es nachprüfbar ist. - Spielmechanik. Würfelwürfe, Kartenmischen, Lootdrops, prozedurale Generierung.
Math.random()ist die Standardwahl, schnell, gleichmäßig genug, unvorhersehbar genug, dass Spieler keine Muster erkennen. CSPRNGs sind reserviert für Online-Kartenspiele, in denen die Serverseite Betrug verhindern muss. - Bucket-Zuweisung für A/B-Tests. Die Benutzer-ID mit einem stabilen Geheimnis hashen, um jeden Benutzer deterministisch in einen Bucket zu legen,
Math.random()hieße, dass ein Benutzer zwischen Seitenladungen in verschiedenen Buckets landet, was das Experiment ruinieren würde. Hash-basierte Zuweisung ist das richtige Muster; Zufall wird nur einmal verwendet, um die Saat des Experiments zu wählen. - Zufallsstichprobe für Umfragen. Eine repräsentative Teilmenge aus einer Population ziehen.
Math.random()reicht; die statistische Frage ist, ob deine Stichprobe groß genug ist, nicht, ob die Zufallsquelle kryptografisch ist. - Generierung von Testdaten. Faker, Mockup-Daten, synthetische Datenbank-Fixtures.
Math.random()mit fester Saat (für Reproduzierbarkeit) ist die richtige Wahl. - Kryptografische Schlüssel, Sitzungs-Tokens, Passwort-Erzeugung. Nur CSPRNG,
crypto.getRandomValues()im Browser, das Modulsecretsin Python,crypto/randin Go, niemals der Sprachstandard-Zufall. Ein Bug in dieser Schicht kompromittiert alles, was darauf aufbaut; die Folgen reichen von „jede Sitzung ist kaperbar“ bis „der Verschlüsselungsschlüssel ist rekonstruierbar“.
RANDOM.ORG und die Unterscheidung von echtem Zufall
RANDOM.ORG wurde 1998 von Mads Haahr am Trinity College Dublin gestartet und bleibt der Goldstandard für „echten Zufall“ im Netz. Wo jeder CSPRNG seine Bits letztlich aus algorithmischen Transformationen eines hardware-gespeisten Zustands ableitet (ein deterministischer Prozess, auch wenn unvorhersehbar für einen Angreifer), misst RANDOM.ORG atmosphärisches Rauschen aus Funkempfängern und wandelt das analoge Rauschen direkt in Bits. Das macht es zu einem True Random Number Generator (TRNG) statt eines Pseudozufallszahlengenerators: die Bits stammen aus einem physikalischen Prozess, der echt nicht-deterministisch ist, nicht aus einem deterministischen Algorithmus. RANDOM.ORG wird von Lotteriebetreibern, akademischen Forschern in Doppelblind-Studien und Spielen genutzt, in denen verifizierbarer Zufall zählt. Der Kompromiss: ein Netzwerk-Round-Trip pro Anfrage, ein Tageskontingent für die kostenlose Stufe, und die philosophische Frage, ob du der von RANDOM.ORG behaupteten Entropiequelle gegenüber deinem lokalen CSPRNG vertraust. Für die meisten Anwendungsfälle reicht der lokale CSPRNG; für Fälle, in denen eine Drittpartei den Zufall unabhängig verifizieren muss, bietet RANDOM.ORG signierte Zufallszertifikate als kostenpflichtigen Dienst an.
Ziehen ohne Zurücklegen, der Fisher-Yates-Shuffle
Wenn du N eindeutige Zahlen aus einem Bereich brauchst, 6 Zahlen aus 1-49 für eine Lotterie, 10 Gewinner aus 1.000 Teilnehmern, funktioniert das naive „erzeugen und bei Duplikat verwerfen“ für kleine N, degradiert aber stark, wenn N sich der Bereichsgröße nähert (die Chance, eine frische Zahl zu ziehen, sinkt, während der Pool schrumpft). Der Standardalgorithmus ist der Fisher-Yates-Shuffle, der aus den statistischen Tabellen von Fisher und Yates aus 1938 stammt und seine moderne informatik-typische Form 1969 von Donald Knuth bekam (manchmal Knuth-Shuffle genannt). Der Algorithmus ist kinderleicht: schreibe die Zahlen 1 bis N in ein Array; für i von N-1 hinunter bis 1, vertausche das Element i mit einem zufälligen Element zwischen 0 und i (einschließlich); das Array ist nun gleichmäßig gemischt. Nimm die ersten K Elemente für K eindeutige Zufallszahlen. Entscheidendes Detail: der Zufallsindex muss in [0, i] sein, einschließlich, [0, i-1] zu nutzen führt einen subtilen Bias ein, dessen Charakterisierung Jahre der Kryptografie-Community kostete (die Sattolo-Variante, manchmal fälschlich anstelle des echten Fisher-Yates verwendet). Für sehr große Bereiche, in denen ein Array mit allen N Werten unpraktisch ist (z. B. 100 eindeutige Werte aus 1-109), behandelt das Reservoir-Sampling (Vitter, 1985) Stream- oder unbegrenzte Eingaben in einem einzigen Durchgang mit beschränktem Speicher.
Konventionen für Würfelwürfe
Zufallszahlengeneratoren sind verkleidete Würfel. Der D6 (sechsseitiger Würfel) ist der universelle Standard im Brettspiel, Bereich 1-6. Der D20 (zwanzigseitiger Würfel) ist der ikonische Würfel von Dungeons & Dragons für Fertigkeitsproben, Angriffswürfe und Rettungswürfe, das Modifikator-System von D&D macht, dass ein einziger D20-Wurf plus ein Stat-Bonus den Ausgang der meisten Aktionen entscheidet. Der D100 (Prozent, 1-100) wird für Prozentwürfe in Call of Cthulhu, Warhammer Roleplay und vielen Krit-Chance-Systemen verwendet. Die Notation NdM bedeutet „wirf N Würfel mit je M Seiten und summiere“; NdM+B addiert einen Bonus. 3d6 wirft drei sechsseitige Würfel und summiert (Bereich 3-18, der klassische D&D-Attributwert-Bereich, mit einer Dreiecksverteilung um 10-11). Für eine faire Simulation ist das Erzeugen eines gleichverteilten Integers in [1, M] für jeden Würfel und Summieren exakt äquivalent zum Werfen physischer Würfel, die zugrundeliegende CSPRNG-Verteilung ist gleichmäßiger als jeder physische Würfel, den du kaufen könntest. Casinos und reguliertes Spiel nutzen zertifizierte RNGs, die gegen statistische Batterien (BigCrush von TestU01, NIST SP 800-22) getestet werden, um Aufsichtsbehörden Gleichmäßigkeit zu beweisen; dieselben Standards gelten für Lotterie-RNGs.
Saat und Reproduzierbarkeit
Eine subtile, aber wichtige Eigenschaft von PRNGs: sie sind bei gegebener Saat deterministisch. Setze die Saat auf einen bekannten Wert, und die Sequenz der „zufälligen“ Zahlen ist exakt reproduzierbar. Das ist unschätzbar für Tests (ein Unit-Test, der Zufallsdaten nutzt, sollte eine feste Saat setzen, damit Fehler reproduzierbar sind) und für nachprüfbare Verlosungen (vor der Ziehung die Saat veröffentlichen, dann kann jeder das Ergebnis überprüfen). Pythons random-Modul hat dafür random.seed(value); Javas Random nimmt eine Saat im Konstruktor. JavaScripts Math.random() exponiert bewusst keine Saat-API, Engines behandeln die Saat als internen Zustand, aber mehrere reine JS-Bibliotheken (seedrandom, pcg-random) bieten gesäte PRNGs. CSPRNGs sind designgemäß anders: sie exponieren keine Saat, weil der ganze Sinn die Unvorhersehbarkeit ist. Wenn du Reproduzierbarkeit brauchst, nutze einen PRNG mit expliziter Saat; wenn du Sicherheit brauchst, nutze einen CSPRNG und akzeptiere, dass du die Sequenz später nicht reproduzieren kannst.
Datenschutz: Warum nur im Browser, sogar bei Zufallszahlen
Zufallszahlen selbst enthalten selten sensible Information, warum zählt also die reine Browser-Architektur? Zwei Gründe. Erstens: wenn eine Zufallszahl als Sitzungs-Token, Idempotenzschlüssel, Authentifizierungs-Challenge oder ein anderer geheimnisartiger Wert genutzt wird, bedeutet das Erzeugen auf einem Drittserver, dass dieser Server den Wert sah, bevor du ihn nutztest, eine kleine, aber reale Exposition. Zweitens: serverseitige Generatoren, die „kryptografische Zufälligkeit“ versprechen, können vom Benutzer nicht verifiziert werden; ein fehlerhafter oder bösartiger Server könnte nicht-zufällige oder verzerrte Werte zurückgeben, die zufällig aussehen, und du hättest ohne massives Sampling keine Möglichkeit, den Bias zu entdecken. Ein reiner Browser-Generator führt denselben crypto.getRandomValues()-Aufruf aus, den deine Anwendung serverseitig ausführen würde; die Entropie kommt aus derselben Betriebssystemquelle (Linux getrandom(), Windows BCryptGenRandom, macOS); keine Drittpartei sieht die Ausgabe. Du kannst es verifizieren, indem du den Network-Tab der DevTools öffnest, während du auf Generieren klickst, es gibt keine ausgehenden Anfragen. Setze die Seite nach dem Laden offline (Flugmodus), und der Generator funktioniert weiter.
Häufig gestellte Fragen
Sind diese Zahlen kryptografisch sicher?
Ja. Der Generator nutzt crypto.getRandomValues() der Web Crypto API mit Rejection Sampling, um gleichmäßige Integer über jeden Bereich zu erzeugen. Die Entropie kommt aus dem CSPRNG des Betriebssystems, Linux getrandom(), Windows BCryptGenRandom, macOS, dieselbe Quelle, die TLS für Sitzungsschlüssel nutzt. Geeignet für sicherheitsrelevante Anwendungen: Lotterieziehungen, Sitzungs-Tokens, Idempotenzschlüssel, Passwort-Erzeugung.
Warum nicht einfach Math.random() nutzen?
Für Spielmechanik, Simulationen, A/B-Test-Bucketing oder alles, wo Unvorhersehbarkeit keine Sicherheitsanforderung ist, reicht Math.random(), schnell, gleichmäßig genug, überall verfügbar. Für alles, was ein Angreifer vorherzusagen versuchen könnte, Sitzungs-Tokens, Passwort-Erzeugung, Sicherheits-IDs, Lotterieziehungen, ist Math.random() gefährlich. Der Zustand kann aus wenigen Ausgaben rekonstruiert werden, die Sequenz ist von jedem Ausgangspunkt aus reproduzierbar, und die Periode (auch wenn groß in modernen Engines) ist implementierungsabhängig und nicht als kryptografisch beworben. Die Kosten des Wechsels zu crypto.getRandomValues() sind auf moderner Hardware praktisch null; mache es zur Voreinstellung, sobald die Antwort zählt.
Kann ich ohne Duplikate generieren?
Ja, aktiviere die Option „Nur eindeutige“. Das nutzt einen Fisher-Yates-Shuffle (der Standardalgorithmus seit Fisher und Yates 1938; in seiner modernen informatik-typischen Form 1969 von Knuth) zum Ziehen von N eindeutigen Werten aus deinem Bereich ohne Bias. Für kleine N relativ zur Bereichsgröße sind die Kosten vernachlässigbar; für N nahe der Bereichsgröße läuft der Algorithmus immer noch in O(N). Der klassische Anwendungsfall sind Lotterie-artige Ziehungen (6 eindeutige Zahlen aus 1-49), bei denen Duplikate ungültig wären.
Gibt es einen Unterschied zu RANDOM.ORG?
Ja. RANDOM.ORG (Mads Haahr, Trinity College Dublin, 1998) ist ein True Random Number Generator (TRNG), seine Bits kommen aus atmosphärischem Rauschen, gemessen von Funkempfängern, einem echt nicht-deterministischen physikalischen Prozess. Dieser Generator ist ein Cryptographically Secure Pseudo-Random Number Generator (CSPRNG), seine Bits sind bei gegebenem OS-Entropiezustand deterministisch, aber unvorhersehbar für jeden Angreifer ohne Zugriff auf diesen Zustand. Für die meisten Anwendungsfälle ist CSPRNG nicht von TRNG zu unterscheiden; für Fälle, in denen eine Drittpartei den Zufall unabhängig verifizieren muss (regulierte Lotterie, wissenschaftliche Doppelblind-Studien), sind die signierten Zufallszertifikate von RANDOM.ORG der Goldstandard, zum Preis eines Netzwerk-Round-Trips und eines Tageskontingents.
Warum sehe ich anderswo „Modulo-Bias“-Warnungen?
Weil die naive Art, ein zufälliges Byte (0-255) auf einen Würfelwurf (1-6) abzubilden, einen kleinen Bias einführt: byte % 6 gibt die Werte 0-3 etwa 2,4 % häufiger als die Werte 4-5, weil 256 nicht gleichmäßig durch 6 teilbar ist. Der Fix ist Rejection Sampling: Bytes ≥ 252 (das größte Vielfache von 6 ≤ 256) verwerfen und neu versuchen. Dieser Generator nutzt Rejection Sampling für alle Integer-Bereiche, daher ist die Ausgabe gleichmäßig ohne detektierbaren Bias. Der Bias zählt vor allem für kryptografische Anwendungen, in denen statistische Angriffe auf verzerrte Ausgaben Schlüsselmaterial rekonstruieren können; bei Spielmechanik ist er unsichtbar.
Werden die Zahlen irgendwohin gesendet?
Nein. Jede Zufallszahl wird lokal in deinem Browser über die Web Crypto API erzeugt. Der Generator macht nie eine Netzwerkanfrage, prüfe es im Network-Tab der DevTools, während du auf Generieren klickst, oder schalte die Seite nach dem Laden offline und bestätige, dass das Werkzeug noch funktioniert. Sicher zum Erzeugen von Sitzungs-Tokens, Lotterieziehungen, Sicherheits-IDs oder beliebigen Zahlen, bei denen du nicht möchtest, dass eine Drittpartei den Wert vor dir gesehen hat.
Verwandte Tools
Passwort-Generator
Erzeugen Sie starke Zufallspasswörter mit anpassbarer Länge und Zeichenoptionen.
UUID-Generator
UUID-v4-Werte zufällig erzeugen. Einzeln oder massenhaft mit Formatoptionen.
Zahlenbasen-Konverter
Zahlen zwischen Binär, Oktal, Dezimal und Hexadezimal konvertieren. Beliebige Genauigkeit.