Frage:
Warum ist Math.random () nicht kryptografisch sicher?
forest
2018-03-15 11:11:06 UTC
view on stackexchange narkive permalink

Die JavaScript-Funktion Math.random () gibt einen einzelnen IEEE-Gleitkommawert n zurück, sodass 0 ≤ ist n < 1. Es ist allgemein bekannt (oder sollte es zumindest sein), dass die Ausgabe nicht kryptografisch sicher ist. Die meisten modernen Implementierungen verwenden den Algorithmus XorShift128 +, der leicht beschädigt werden kann. Da es nicht ungewöhnlich ist, dass Menschen es fälschlicherweise verwenden, wenn sie eine bessere Zufälligkeit benötigen, warum ersetzen Browser es nicht durch ein CSPRNG? Ich weiß, dass Opera das tut * zumindest. Der einzige Grund, den ich mir vorstellen könnte, wäre, dass XorShift128 + schneller als ein CSPRNG ist, aber auf modernen (und auch nicht so modernen) Computern wäre es trivial, Hunderte von Megabyte pro Sekunde mit ChaCha8 oder AES-CTR auszugeben. Diese sind häufig schnell genug, sodass eine gut optimierte Implementierung möglicherweise nur durch die Speichergeschwindigkeit des Systems eingeschränkt wird. Selbst eine nicht optimierte Implementierung von ChaCha20 ist auf allen Architekturen extrem schnell, und ChaCha8 ist mehr als doppelt so schnell.

Ich verstehe, dass es nicht als CSPRNG neu definiert werden konnte, da der Standard ausdrücklich keine Garantie dafür gibt Eignung für die kryptografische Verwendung, aber es scheint keinen Nachteil für Browser-Anbieter zu geben, die dies freiwillig tun. Dies würde die Auswirkung von Fehlern in einer großen Anzahl von Webanwendungen verringern, ohne gegen den Standard zu verstoßen (es muss nur eine Ausgabe sein, die auf geradzahlige IEEE 754 -Nummern gerundet ist), die Leistung verringert oder die Kompatibilität beeinträchtigt mit Webanwendungen.


BEARBEITEN: Einige Leute haben darauf hingewiesen, dass dies möglicherweise dazu führen kann, dass Leute diese Funktion missbrauchen, selbst wenn der Standard besagt, dass Sie sich für die kryptografische Sicherheit nicht darauf verlassen können. Meiner Meinung nach gibt es zwei gegensätzliche Faktoren, die bestimmen, ob die Verwendung eines CSPRNG einen Nettosicherheitsvorteil darstellt oder nicht:

  1. Falsches Sicherheitsgefühl - Die Anzahl der Personen, die andernfalls eine für diesen Zweck entwickelte Funktion verwenden würden, z. B. window.crypto , entscheiden Sie sich stattdessen für die Verwendung von Math.random () , da es auf der vorgesehenen Zielplattform kryptografisch sicher ist.

  2. Opportunistisch Sicherheit - Die Anzahl der Personen, die es nicht besser wissen und ohnehin Math.random () für vertrauliche Anwendungen verwenden, die vor ihrem eigenen Fehler geschützt wären. Natürlich wäre es besser, sie stattdessen zu erziehen, aber dies ist nicht immer möglich.

  3. ol>

    Es scheint sicher anzunehmen, dass die Anzahl der Personen vor ihren eigenen geschützt wäre Fehler würden die Anzahl der Personen, die in ein falsches Sicherheitsgefühl versetzt werden, bei weitem übersteigen.

    * Wie CodesInChaos hervorhebt, trifft dies jetzt nicht mehr zu, da Opera auf Chrom basiert. sub>


    Mehrere große Browser haben Fehlerberichte erhalten, in denen vorgeschlagen wurde, diese Funktion durch eine kryptografisch sichere Alternative zu ersetzen, aber keine der vorgeschlagenen sicheren Änderungen ist gelandet:

Die Argumente für Die Änderung entspricht im Wesentlichen meiner. Die Argumente dagegen variieren von reduzierter Leistung auf Mikrobenchmarks (mit geringen Auswirkungen in der realen Welt) bis zu Missverständnissen und Mythen, wie der falschen Vorstellung, dass ein CSPRNG mit der Zeit schwächer wird, wenn mehr Zufälligkeit erzeugt wird. Am Ende erstellte Chromium ein völlig neues Kryptoobjekt, und Firefox ersetzte sein RNG durch den XorShift128 + -Algorithmus. Die Funktion Math.random () bleibt vollständig vorhersehbar.

Kommentare sind nicht für eine ausführliche Diskussion gedacht.Diese Konversation wurde [in den Chat verschoben] (https://chat.stackexchange.com/rooms/74736/discussion-on-question-by-forest-why-is-math-random-not-designed-to-be-Kryptog).
Zu sagen, dass ein Merkmal bestimmte Eigenschaften hat, bedeutet Verpflichtung.Die Verpflichtung verursacht Kosten, erstens, um die Verpflichtung umzusetzen, zweitens, um sie auf dem neuesten Stand zu halten, und drittens, wenn Sie feststellen, dass Sie Ihrer Verpflichtung nicht nachgekommen sind.Dies gilt insbesondere dann, wenn Sie verpflichtet sind, ** sichere ** Funktionen bereitzustellen.
@MichaelK Aber es gibt so viele andere Beispiele, bei denen das nicht stimmt.Sie müssen nicht sagen, dass eine Funktion irgendwo bestimmte Eigenschaften hat.Behalten Sie den Standard bei und verbessern Sie die Sicherheit opportunistisch.Ein gutes Beispiel ist jeder moderne C-Compiler.Würden Sie behaupten, dass es dumm ist, wenn der Compiler "FORTIFY_SOURCE" unterstützt?Warum nicht einfach Menschen erziehen, damit sie keine verletzlichen Programme machen?Warum hat GCC sie beschützt?Ich kenne niemanden, der in seinem Code schlampig ist, weil er glaubt, dass GCC sie schützen wird, aber ich kenne viele Menschen, die durch die Sicherheitsmaßnahmen von GCC gerettet wurden.
Mit anderen Worten, Sie sagen, dass ausfallsicheres Design eine schlechte Sache ist.
@forest Opportinistische Sicherheit?Worte, von denen ich nie gedacht hätte, dass sie jemand sagen würde.
Leistung vielleicht?Das Erhalten eines kryptografisch sicheren Zufallswerts ist viel CPU-schwerer als ein Pseudozufallswert.Beim Entwerfen eines Spiels (in C ++) musste ich speziell einen zufälligen Algorithmus auswählen, der eine anständige Leistung bietet.
Blink ist eine Rendering-Engine.V8 ist die von Chrome und Opera verwendete JavaScript-Implementierung.
@Rolf ツ Dieses Problem wurde in Antworten und Kommentaren ausführlich erörtert.Die Leistung von XorShift128 + im Vergleich zu beispielsweise ChaCha8, das für die Rückgabe einzelner Gleitkommazahlen verwendet wird.
Der Vergleich der Leistung von XorShift128 + mit ChaCha8 ist nur ein Teil der Leistungsfrage.Ein CSPRNG muss eine ausreichende Entropie sammeln, bevor es bereit ist, sichere Zufallsbits zu emittieren.Dies kann eine erhebliche Wanduhrzeit in Anspruch nehmen.
@JamesKPolk Sie benötigen nur einmal 128 Bit (ChaCha benötigt 256 Bit, aber es ist durchaus akzeptabel, den Schlüssel zweimal zu wiederholen, solange Sie die Konstante ändern).Wenn ein Browser geladen wird, steht dem System ausreichend Entropie zur Verfügung.Auf Mikrocontrollern, auf denen aus irgendeinem Grund ein JavaScript-Interpreter ausgeführt wird und die keine gute Entropiequelle haben, können sie einfach XorShift128 + verwenden (da ich keine Änderung der Standards vorschlage).
@forest: fair genug, sollte es in der Tat kein Problem auf jeder modernen Plattform, Desktop oder Handy sein.
Elf antworten:
Eric Lippert
2018-03-15 20:10:44 UTC
view on stackexchange narkive permalink

Ich war Mitte bis Ende der neunziger Jahre einer der Implementierer von JScript und Mitglied des ECMA-Ausschusses, daher kann ich hier eine historische Perspektive bieten.

Die JavaScript-Funktion Math.random () ist so konzipiert, dass ein Gleitkommawert zwischen 0 und 1 zurückgegeben wird. Es ist allgemein bekannt (oder sollte es zumindest sein), dass die Ausgabe nicht kryptografisch sicher ist.

Zunächst einmal: das Design vieler RNG APIs sind schrecklich . Die Tatsache, dass die .NET Random-Klasse auf verschiedene Weise trivial missbraucht werden kann, um lange Sequenzen derselben Nummer zu erzeugen, ist schrecklich. Eine API, bei der die natürliche Verwendung auch die falsche ist, ist eine "Pit of Failure" -API. Wir möchten, dass unsere APIs Erfolgsgruben sind, in denen der natürliche und der richtige Weg gleich sind.

Ich denke, es ist fair zu sagen, dass die JS-Zufalls-API anders wäre, wenn wir damals wüssten, was wir jetzt wissen. Selbst einfache Dinge wie das Ändern des Namens in "Pseudozufall" würden helfen, da, wie Sie bemerken, in einigen Fällen die Implementierungsdetails von Bedeutung sind. Auf architektonischer Ebene gibt es gute Gründe, warum Sie möchten, dass random () eine Factory ist, die ein Objekt zurückgibt, das eine zufällige oder pseudozufällige Sequenz darstellt, anstatt einfach Zahlen zurückzugeben. Und so weiter. Lektionen gelernt.

Zweitens wollen wir uns daran erinnern, was der grundlegende Entwurfszweck von JS in den 1990er Jahren war. Lassen Sie den Affen tanzen, wenn Sie die Maus bewegen . Wir haben Inline-Ausdrucksskripte als normal angesehen, wir haben zwei- bis zehnzeilige Skriptblöcke als üblich angesehen, und die Vorstellung, dass jemand hundert Zeilen Skript auf eine Seite schreiben könnte, war wirklich sehr ungewöhnlich. Ich erinnere mich an das erste Mal, als ich ein JS-Programm mit zehntausend Zeilen sah, und meine erste Frage an die Leute, die mich um Hilfe baten, weil es im Vergleich zu ihrer C ++ - Version so langsam war, war eine Version von "Bist du verrückt?! 10KLOC JS?!" "

Die Vorstellung, dass jeder Krypto-Zufälligkeit in JS benötigen würde, war ähnlich verrückt. Sie brauchen Ihre Affenbewegungen, um eine unvorhersehbare Kryptostärke zu haben? Unwahrscheinlich.

Denken Sie auch daran, dass es Mitte der 90er Jahre war. Wenn Sie nicht dafür da waren, kann ich Ihnen sagen, dass es in Bezug auf Krypto eine ganz andere Welt als heute war ... Siehe Export von Kryptografie.

Ich hätte nicht einmal in Betracht gezogen, die Zufälligkeit der Kryptostärke in irgendetwas zu stecken, das mit dem Browser geliefert wird, ohne eine große Menge an Rechtsberatung vom MSLegal-Team zu erhalten. Ich wollte Krypto nicht mit einer zehn Fuß langen Stange in einer Welt berühren, in der der Versandcode als Export von Munition an Staatsfeinde angesehen wurde. Das klingt aus heutiger Sicht verrückt, aber das war die Welt, die war.

Warum ersetzen Browser es nicht durch ein CSPRNG?

Browserautoren müssen keinen Grund angeben, KEINE Änderung vorzunehmen. Änderungen kosten Geld und nehmen den Aufwand für bessere Änderungen weg. Jede Änderung hat enorme Opportunitätskosten .

Vielmehr müssen Sie nicht nur argumentieren, warum die Änderung eine gute Idee ist, sondern auch, warum sie ihre Zeit bestmöglich nutzt. Dies ist eine kleine Änderung.

Ich verstehe, dass sie nicht als CSPRNG neu definiert werden konnte, da der Standard ausdrücklich keine Garantie für die Eignung für die kryptografische Verwendung gibt. Es scheint jedoch keinen Nachteil zu geben,

Der Nachteil ist, dass Entwickler immer noch in einer Situation sind, in der sie nicht zuverlässig wissen können, ob ihre Zufälligkeit Kryptostärke ist oder nicht, und kann noch leichter in die Falle tappen, sich auf eine Eigenschaft zu verlassen, die nicht durch den Standard garantiert wird. Die vorgeschlagene Änderung behebt das Problem nicht, bei dem es sich um ein Entwurfsproblem handelt.

(Bit off topic) Würde es Ihnen etwas ausmachen, eine Referenz für "Die .NET Random-Klasse kann trivial auf verschiedene Arten missbraucht werden, um lange Sequenzen derselben Nummer zu erzeugen, ist schrecklich" anzugeben?: Ich habe noch nie davon gehört, oder sind Sie es?unter Bezugnahme auf den Klassiker "Erstellen Sie tausend zufällige Instanzen in einer engen Schleife"?
@VisualMelon: Tausend Instanzen in einer engen Schleife erstellen ist der Klassiker.Es gibt aber auch Fehlermodellen, wenn man gleichzeitig eine Instanz von Random auf zwei Threads gleichzeitig nutzt.Random ist nicht threadsicher und es gibt ein Szenario, in dem ein Rennen dazu führen kann, dass es für immer null zurückkehrt!
@VisualMelon: Es gibt auch subtilere Szenarien.Angenommen, Sie haben zwei Instanzen von Random mit unterschiedlichen Startwerten.Scheint in Ordnung zu sein, oder?Angenommen, Sie kombinieren diese beiden Instanzen von Random auf irgendeine Weise.Vielleicht verwenden Sie sie, um jeweils eine Folge von Würfelwürfeln zu erzeugen und sie paarweise zu addieren.** Sind die beiden Sequenzen nicht zufällig miteinander korreliert **?Es scheint plausibel.Immerhin führen sie denselben Algorithmus "parallel" aus, nur mit einem anderen Startwert.
Vielen Dank für die Ausarbeitung: Ich bin wahrscheinlich vorsichtig genug, um nicht zu versuchen, eine Quelle aus mehreren Threads zu verwenden, es sei denn, sie ist zu diesem Zweck eindeutig dokumentiert, sodass ich es nie bemerken würde.Ich bin mir nicht sicher, ob der letzte Punkt ein spezifisches Anliegen für eine 'Implementierung' ist und nicht der Algorithmus dahinter: Ich glaube nicht, dass wir die API-Designer dafür zur Rechenschaft ziehen können!
Ich denke, dies ist die bisher beste Antwort hier, zumal sie aus einer so maßgeblichen Quelle stammt.Ich werde diese Antwort vorerst als akzeptiert markieren, es sei denn, es kommt eine bessere Antwort.
@EricLippert Ich verstehe Ihre 2 Streams mit verschiedenen Schlüsseln nicht zusammen Beispiel.Wenn es ein CSPRNG ist, dann würde ich denken, dass das in Ordnung sein sollte.Wenn es sich nicht um ein CSPRNG handelt (nur um ein Plan-PRNG), sollten Sie es niemals aus Sicherheitsgründen verwenden, selbst wenn Sie nur eine einzige Instanz haben.
@Buge: Es ist ziemlich leicht, sich ein (nicht sehr gutes) RNG vorzustellen, das ganze Zahlen erzeugt und bei dem das untere Bit der Ausgabe zufällig, aber unabhängig vom Startwert ist.Wenn Sie die Ausgabe von zwei solchen Instanzen hinzufügen (unabhängig voneinander gesetzt), ist das Ergebnis immer gerade.(Erics Argument hatte nichts mit Sicherheit zu tun - ich weiß nicht, warum Sie das gedacht haben.)
Ja!Warum sind * alle * zufälligen APIs auf * allen * Plattformen so durcheinander?Ich denke, die Teams sagen "Lass den Praktikanten das machen".
@EricLippert Ich denke, es lohnt sich, dieser Antwort von C #s missbräuchlichem "Zufall" ein konkretes Beispiel hinzuzufügen.So etwas wie dieser (Pseudo-) Code: `while (etwas) {int rand = new Random (). NextInt ();doSomething (rand);} `- Das schlägt fehl, weil C # 's' Random` die aktuelle Zeit mit Kursauflösung als Startwert verwendet. Wenn also` doSomething` schnell ist, erhalten Sie immer wieder die erste Zahl in der Sequenz mit dem Startwert dieser Zeitwieder eher als andere.(Ich weiß, dass Sie das wissen; ich erkläre es den Leuten, die nicht mit Microsoft an C # gearbeitet haben)
@Buge Tatsächlich kann das Mischen mehrerer fehlerhafter PRNGs manchmal zu einer anständigen Verschlüsselung führen, zumindest wenn dies richtig gemacht wird.Zum Beispiel umfasst E0 (die Verschlüsselung, die von allen außer den neuesten Bluetooth-Protokollen verwendet wird) vier LFSRs.Jeder einzelne LFSR ist trivial zu brechen, aber E0 selbst ist ein gutes Stück stärker (aber immer noch nicht großartig).
@MartinBonner Ich dachte, in Erics Kommentar ging es um CSPRNGs, da dies security.stackexchange.com ist und sowohl die Frage als auch Erics Antwort über CSPRNGs sprachen.
@forest Ich hätte meine Aussage einschränken sollen, indem ich sagte: "Wenn es sich nicht um ein CSPRNG (nur ein einfaches PRNG) handelt, sollten Sie es niemals aus Sicherheitsgründen verwenden, es sei denn, Sie sind ein Kryptographie-Experte."So wie ein Kryptoexperte mithilfe unsicherer Grundelemente wie Addition, XOR und Multiplikation eine neue Verschlüsselung erstellen kann, kann ein Kryptoexperte auch mithilfe von PRNGs ein neues CSPRNG erstellen.Und so wie ein Laie niemals eine neue Verschlüsselung mit unsicheren Grundelementen erstellen sollte, sollte ein Laie niemals ein PRNG für die Sicherheit verwenden.
Eine ausgezeichnete, informative Antwort.Die „Opportunitätskosten“ sind wahrscheinlich die einzige wirkliche Erklärung, aber alles andere ist ein wahrer Genuss
Ich wollte eine sehr ähnliche Antwort geben, die zu denselben hier erwähnten Themen gespielt wurde, im Grunde genommen die kurze, unbefriedigende Version davon: "Die Spezifikation erfordert es nicht, daher müssen Implementierungen es nicht kryptografisch zufällig machen."
@Buge Die Argumentation, die Martin verwendet, gilt für CSPRNGs.Nicht besonders gute wohlgemerkt, aber dann sind die meisten CSPRNGs, die von Mainstream-Sprachen verwendet werden, alles andere als erstaunlich.
@Voo Wenn "das untere Bit der Ausgabe zufällig, aber unabhängig vom Startwert ist", handelt es sich nicht um ein CSPRNG.Ein CSPRNG [erfordert] (https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator), dass die Ausgabe des CSPRNG nicht von der tatsächlichen Zufälligkeit zu unterscheiden ist, wenn Sie keine Kenntnis des Seeds haben.Aber dieses schlechte PRNG ist ziemlich leicht von wahrer Zufälligkeit zu unterscheiden, selbst ohne Kenntnis des Samens.Überprüfen Sie einfach, ob das untere Bit dem Muster folgt.
@Buge Ich dachte an eine gemeinsame Zufallsquelle (z. B. ein Hardwaremodul).Aber Sie haben Recht, dass das nicht funktionieren würde, wenn Sie zwei Sequenzen hätten.
Philipp
2018-03-15 15:22:47 UTC
view on stackexchange narkive permalink

Weil es tatsächlich eine kryptografisch sichere Alternative zu Math.random():

window.crypto.getRandomValues ​​(typedArray) gibt

Dadurch kann der Entwickler das richtige Tool für den Job verwenden. Wenn Sie hübsche Bilder oder Beutetropfen für Ihr Spiel generieren möchten, verwenden Sie den schnellen Math.random () . Wenn Sie kryptografisch sichere Zufallszahlen benötigen, verwenden Sie das teurere Fenster window.crypto .

Warum würden Sie keine sichere Zufallsfunktion für Beutetropfen verwenden?
@xDaizu Weil nicht jeder Beutetropfen eine Beutekiste ist, in der jemand eine echte Lotterie daraus machen wird.
Wenn Ihre Beute kryptografisch sicher sein muss * und * Sie ein clientseitiges RNG verwenden, um die Beute zu generieren (anstatt den Server zu fragen "Was habe ich bekommen?"), Tun Sie höchstwahrscheinlich etwas falsch.
Dies beantwortet nicht die Frage ... Forest fragt, warum "Math.Random ()" so implementiert ist, wie es ist, und nicht, wie ein CSPRNG in Javascript verwendet wird
Genauer gesagt ist `window.crypto` weitgehend nutzlos, wenn Sie dem Benutzer nicht vertrauen.In diesem speziellen Fall können sie (oder ihr Benutzeragent oder alle vertrauenswürdigen Proxys) ihn einfach durch "() => 0,42" ersetzen, bevor er ausgeführt wird.Dies sind Dienstprogramme, mit denen der Benutzer Sicherheit einrichten kann, nicht Sie.
@xDaizu Ihre Frage wird in dem Beitrag beantwortet, auf den Sie geantwortet haben: Es geht um "schnell gegen [langsam und] teuer".
@OrangeDog, Deshalb müssen Sie immer das Schlüsselwort `const` verwenden.
@NH.Nichts, das Sie im Skript schreiben, wird helfen, der Benutzer hat die vollständige Kontrolle darüber.
@OrangeDog, ist das ein CVE?Wenn nicht, können Sie Ihre Bedenken als separaten Beitrag veröffentlichen (wir beginnen, vom Thema abzuweichen ...)
@OrangeDog Das stimmt, aber es stimmt, weil es um clientseitiges Scripting geht.Es hat nichts mit der Tatsache zu tun, dass "Math.random" nicht kryptografisch sicher ist.
Luc
2018-03-15 16:13:53 UTC
view on stackexchange narkive permalink

JavaScript (JS) wurde 1995 erfunden.

  1. Potenziell illegal: Kryptografie war 1995 noch unter strenger Exportkontrolle, sodass ein gutes CSPRNG möglicherweise nicht einmal über eine solche verfügt Die Verteilung in einem Browser war legal.
  2. Leistung: In der Vergangenheit sind CSPRNGs (kryptografisch sichere Pseudozufallszahlengeneratoren) viel langsamer als PRNGs. Warum also standardmäßig ein CSPRNG verwenden?
  3. Keine Sicherheitsphilosophie: 1995 wurde SSL gerade erfunden. Es wurden praktisch keine Server unterstützt, das Internet bestand aus Telefonleitungen und wurde für öffentliche Foren ( BBSes) und MUDs verwendet. Verschlüsselung war etwas für Geheimdienste.
  4. Keine Notwendigkeit: Webanwendungen existierten noch nicht, da JavaScript gerade erfunden wurde. Es wurde als interpretierte (also langsame) Sprache entwickelt, um Seiten dynamischer zu machen. Es wäre niemandem in den Sinn gekommen, standardmäßig ein langsames (und kaum vorhandenes) CSPRNG für eine Zufallsfunktion zu verwenden.
  5. Tatsächlich gab es so wenig Bedarf, dass es keine Alternative gab: JavaScript hatte bis Dezember 2013 nicht einmal eine allgemein unterstützte API für ein CSPRNG, sodass eine ordnungsgemäße Kryptografie in Webanwendungen bis vor einigen Jahren kaum möglich war.
  6. Konsistenz: Anstatt eine vorhandene Funktion in eine andere Bedeutung zu ändern, haben sie eine neue Funktion mit einem anderen Namen erstellt. Sie können jetzt über crypto.getRandomValues ​​ auf das CSPRNG zugreifen.
  7. ol>

    Zusammenfassend: Legacy, aber auch Geschwindigkeit und Konsistenz . Unsichere PRNGs sind immer noch viel schneller, da Sie nicht davon ausgehen können, dass die gesamte Hardware AES-Unterstützung bietet, und auch nicht von der Verfügbarkeit oder Sicherheit von RDRAND abhängen.

    Ich persönlich denke, es ist Zeit, alle zufälligen Funktionen gegen CSPRNGs auszutauschen und die schnelleren, unsicheren Funktionen in fast_insecure_random () umzubenennen. Sie sollten nur von Wissenschaftlern oder anderen Personen benötigt werden, die Simulationen durchführen, die viele Zufallszahlen benötigen, bei denen die Vorhersagbarkeit des RNG jedoch keine Rolle spielt. Aber für eine Funktion mit zwei Jahrzehnten Geschichte, in der es erst seit vier Jahren (2018) eine Alternative gibt, kann ich verstehen, warum wir uns noch nicht an diesem Punkt befinden.

Auch Javascript ist etwas älter als die meisten Leute denken.und die math.random-Funktion ist seit mindestens 1997 darin enthalten (Version 1.1) Eine Zeit, in der niemand so etwas wie Kryptografie in Javascript versuchen würde (SSL selbst sah erst 1995 einige Jahre zuvor kein öffentliches Licht)
Ich bin mit dem letzten Satz nicht einverstanden.Während `crypto.getRandomValues` für sich genommen ein besserer Name gewesen sein könnte, wäre` math.Random` bereits seit einigen Jahren vorhanden, so etwas wie `math.RandomCrypto` wäre eine viel bessere Wahl gewesen, da es als nächstes aufgeführt würdeDer unsichere Aufruf in API-Listen und eine gute automatische Vervollständigung würden beide Versionen immer dann aufrufen, wenn ein Entwickler "math.rando" eingibt, was es weitaus wahrscheinlicher macht, dass er erkennt, dass er die neue Version verwenden sollte, wenn er sie benötigt.
semantisch ist Ihr Vorschlag falsch.Sie möchten zufällige Werte erhalten, die kryptografisch einwandfrei sind.keine zufällige Kryptofunktion / ciper / etc. erhalten. Außerdem geht es in der Mathematikbibliothek nur um mathematische Funktionen.Ein CSPRNG ist eine kryptografische Funktion und daher Eigentum in der Kryptobibliothek.(Und vergessen Sie nicht, dass das Hinzufügen zum Standard einen Konsens aller verschiedenen Motorenhersteller erfordert.)
@DanNeely Ich verstehe Ihren Standpunkt, bin mir aber nicht sicher, wie ich ihn am besten ändern soll.Fühlen Sie sich frei zu bearbeiten!
@LvB Ich bin offen für verschiedene Namen für die Funktion (`math.RandomSecure`?) Oder habe sogar die Implementierung in` crypto. * `Mit nur einem Alias unter` math. * `(Ist modern js in der Lage, den Alias zu inlineVermeiden Sie Overhead durch einen zusätzlichen Funktionsaufruf, um den Alias zu implementieren?).Aber mit der großen Anzahl verschiedener Tools, die zum Bearbeiten von Javascript verwendet werden, maximiert die Verwendung des alten Namens als ersten Teil des neuen die Wahrscheinlichkeit, dass ein Editor Entwicklern die sichere Zufallsquelle vorschlagen kann.
@DanNeely Sie versuchen hier ein menschliches Problem mit technischen Mitteln zu lösen.e.a.Der Mensch sollte lernen, welches Tool wo verwendet werden soll, und nicht die IDE, die eine praktische Funktion verwendet, um das richtige vorzuschlagen.(Es wäre besser, die IDE zu haben, als die richtige vorzuschlagen, aber das ist IDE-abhängig).Es würde auch nicht all jenen Leuten helfen, die Javascript in Browser / vim / nano / notepad / Steintablett / Lochkarte / oder einem anderen Texteditor oder einer direkten Eingabemethode schreiben.Außerdem müssten Sie viele Motorenentwickler zur Hand haben, Leute, die nicht leicht zu überzeugen sind.
@DanNeely Sie können nicht zustimmen, was Sie wollen, Sie sind nicht im TC39-Ausschuss, noch ist dies das richtige Forum, um mit ihren Entscheidungen zu streiten.FWIW, Sie können Ihren eigenen Vorschlag mehrfach ausfüllen, indem Sie einfach `Math.randomCrypto = function () {const u = new Uint32Array (1) zuweisen.crypto.getRandomValues (u);return u [0] / 2 ** 32;} `.Natürlich gibt es mögliche Optimierungen, aber dies ist nur eine Beispielimplementierung.
Jared Smith
2018-03-15 16:56:31 UTC
view on stackexchange narkive permalink

Dies ist zu lang für einen Kommentar.

Ich glaube, Ihre Frage enthält eine fehlerhafte Prämisse:

auf modernen (und sogar nicht so modernen) Computern, Es wäre trivial, mit ChaCha8 oder AES-CTR Hunderte von Megabyte pro Sekunde auszugeben.

Sie denken an einen Desktop-Browser auf einem mit Wechselstrom verbundenen Computer oder einem Laptop mit einem großen 10-Ah-Akku von Honkin.

Wir leben in einer zunehmend mobilen Welt, und obwohl mobile Geräte heutzutage recht leistungsfähig sind, gibt es zwei wichtige Einschränkungen: Wärme und Akkulaufzeit. Im Gegensatz zu einem Desktop-Prozessor, der leicht 100 ° C erreichen kann, können Sie dem Smartphone-Benutzer nicht die Hand abbrennen. Und Telefonbatterien halten normalerweise nur vielleicht 1/3 so viel wie ein Laptop (wenn Sie Glück haben). Es gibt einfach keinen guten Grund, die zusätzliche Wärmeerzeugung / den zusätzlichen Stromverbrauch hinzuzufügen, wenn Sie sie nicht benötigen.

Ich bezweifle, dass Sie den Unterschied zwischen Leistung und Stromverbrauch zwischen Krypto- und Nicht-Krypto-RNG für typischen Code selbst auf Mobilgeräten bemerken würden.Sie müssten eine Monte-Carlo-Simulation in Javascript schreiben.Wir sprechen von ungefähr 30 CPU-Zyklen für jede Nummer.
@CodesInChaos das kann wahr sein.Ich möchte Analysen anzeigen (insbesondere an einem Port eines CRPG), bevor ich diesen Anruf tätige.Aber es ist die implizite Prämisse, dass "Computer jetzt schnell sind, also spielt es keine Rolle", dass dies ein Problem ist.
ChaCha8 kann auf alten Prozessoren etwa 3 Zyklen pro Byte und mit AVX512 weniger als 1 Zyklus pro Byte bereitstellen.XorShift128 + liegt auf einem High-End-Haswell-Prozessor unter 1 Zyklus pro Byte, sodass der Unterschied nicht groß ist.Ich stelle mir vor, dass der bloße Vorgang, den Zufallswert in einen richtigen Gleitkommawert umzuwandeln und ihn zurückzugeben, mehr Zyklen dauert, als den Zufallswert überhaupt zu generieren.
@CodesInChaos Leute schreiben Monte-Carlo-Simulationen in JavaScript.
Wenn ich darüber nachdenke, bin ich mir ziemlich sicher, dass ein Desktop-Prozessor, der 100 ° C erreicht, sehr schlecht wäre.Laptop-Prozessoren können normalerweise damit umgehen (wenn auch nur knapp), aber Desktops?
@CodesInChaos Technisch gesehen benötigen Sie kein kryptografisch starkes RNG für Monte Carlo.Jedes anständige RNG wird funktionieren (wie Mersenne Twister).
@jb.Mein Punkt ist, dass Krypto-RNGs für praktisch jeden Anwendungsfall schnell genug sind und daher die Standardeinstellung sein sollten.Monte-Carlo-Simulationen sind einer der wenigen Fälle, in denen Sie Qualität gegen Leistung eintauschen möchten.
@CodesInChaos Da `Math.random ()` nur einzelne Gleitkommawerte zurückgibt und für jeden neuen Wert aufgerufen werden muss, wäre es eine ziemlich schreckliche Möglichkeit, Zufälligkeit für Monte-Carlo-Simulationen zu erhalten, unabhängig davon, ob XorShift128 + oder ChaCha ist oder nichtgebraucht.Auch das LSB von XorShift128 + ist ein LFSR, das für solche Simulationen wahrscheinlich nicht sehr gut ist.
@CodesInChaos: Der Unterschied beim * Generieren * von Bytes ist wahrscheinlich gering, aber niemand scheint den schwierigeren Teil eines CSPRNG erwähnt zu haben: das Sammeln von Entropie.
Der Browser kann die vom Betriebssystem erzeugten Zufallsdaten problemlos verwenden
@JamesKPolk: Wenn es eine Möglichkeit gibt, dass der Zustand eines CSPRNG aufgedeckt wurde, ist es notwendig, ihn mit einer Entropiequelle neu zu besäen, die von einer vorherigen unabhängig ist, aber wenn man einen guten CSPRNG mit z.4096 Zustandsbits, die z.B.Gibt es Angriffe, die praktisch wären und nicht praktikabel wären, wenn sie mit 4096 Bit Entropie ausgesät würden?
@forest: Es ist nicht so, dass eine Desktop-CPU sicher mehr Temperatur tolerieren kann (dies ist nicht möglich, obwohl die Grenze normalerweise einer mobilen CPU ähnlich ist, z. B. 90, 95 oder 100 ° C).Es ist so, dass die meisten Desktop-CPUs mit effizienter Kühlung installiert werden, sodass sie bei kryptografischen Vorgängen mit voller Neigung ausgeführt werden können und dennoch relativ kühl bleiben, vielleicht 60 ° C.Sie können diese Kühllösung einfach nicht in ein Handheld-Gerät einbauen, unter anderem, weil sie mehr wiegt und größer als der Rest des Telefons ist und nur mit Lüftungsschlitzen und Luftstrom funktioniert. Dies ist für einen wasserfesten Handheld, der sich möglicherweise in einem Handheld befindet, nicht akzeptabelTasche.
@BenVoigt Oh huh, ich hätte schwören können, dass der Tj Max für Desktop-CPUs viel niedriger ist als der von Laptops.Ich muss mich falsch erinnert haben.
LSerni
2018-03-15 12:15:35 UTC
view on stackexchange narkive permalink

Der größere Grund ist, dass es eine Alternative zu Math.random () gibt: siehe Philipps Antwort . Wer also eine starke Krypto benötigt, kann sie haben, und diejenigen, die keine Zeit und (Batterie-) Energie sparen können.

Aber angenommen, Sie hätten gefragt: "Warum, auch wenn es eine stärkere Alternative gibt, haben Sie die Entwickler aktualisieren Math.random () nicht trotzdem - dh haben random () zu einer Ableitung von getRandomValues ​​() gemacht -, um automatisch viele Apps zu stärken? " - dann denke ich nicht, dass dies wirklich mit Sicherheit beantwortet werden kann, außer von den Entwicklern, die die Entscheidung getroffen haben (Update: und wie das Schicksal es haben würde, haben wir eine solche Antwort).

Grundsätzlich gibt es - wie Sie bereits sagten - keinen starken Grund .

Darüber hinaus haben die meisten Entwicklungsteams einen erheblichen Rückstand an Dingen, die dringender sind ;; und selbst eine scheinbar kleine Änderung wie diese erfordert Testen, Regression und einen Verstoß gegen die goldene Regel " Wenn sie nicht gebrochen ist, beheben Sie sie nicht ", eine stärkere Form des YAGNI-Kriteriums.

Ich bin sicher, dass dies auf den Mozilla- und Google-Trackern diskutiert wurde.Vielleicht könnten Sie einige Links bereitstellen, um dies zu zeigen?Ich würde mich damit zufrieden geben, dass die Antwort einfach "weil es noch niemand getan hat" lautet, aber ich würde gerne sehen, dass einige Beispiele dafür zuvor aufgetaucht sind und Entwickler die Idee als unnötig abschießen.
Downvote, weil ich denke, dass es verantwortungsbewusst ist und es albern ist, dies in Fettdruck als Zusammenfassung Ihrer Antwort anzugeben.
@Luc Ich habe die Antwort geändert, um meine Bedeutung zu verdeutlichen - und Philipps Antwort, die meiner Meinung nach die richtige Antwort auf die gestellte Frage ist, positiv bewertet.
Rob
2018-03-16 08:29:02 UTC
view on stackexchange narkive permalink

Zufallszahlen und Kryptozufallsbits sind völlig unterschiedliche Tiere. Sie werden nicht einmal für den gleichen Zweck verwendet. Wenn Sie eine Zufallszahl möchten, die gleichmäßig zwischen 0 und 42 verteilt ist, möchten Sie eine gleichmäßige Verteilung ohne offensichtliches Muster. Beachten Sie, dass es keine gerade Verteilung ist, wenn Sie eine größere Zahl mit einer kleineren modifizieren. Dieses Beispiel ist leicht zu erkennen für eine Zufallszahl von 0 bis 31 aus Mod 27. 0 bis 4 werden doppelt so oft wie 5 bis 31 angezeigt.

Bis Sie über Kryptozufall sprechen, ist der Begriff der Entropie nicht ' Ich habe nicht einmal darüber gesprochen. Ein bisschen Entropie verdoppelt den Suchraum, um die Zahl zu erraten (für den beabsichtigten Benutzer der Zahlen).

Wenn Sie nach Kryptozufallsbits fragen, fragen Sie nach N Entropiebits. Es ist nicht gut genug, ein nicht offensichtliches Muster zu haben, denn wenn eine Funktion entdeckt wird, die es erzeugt (egal wie verworren), dann gibt es tatsächlich 0 Entropiebits aus der Sicht desjenigen, der diese Funktion kennt.

Ein gutes Beispiel hierfür ist ein Fortuna-ähnlicher Pseudozufallszahlengenerator. Sie verschlüsseln eine Nummer 1 mit einem Schlüssel für die erste Zufallszahl (wobei der Verschlüsselungsblock eine große Zahl ist), verschlüsseln dann Nummer 2 mit einem Schlüssel für die zweite Zufallszahl und so weiter. In Bezug auf den Benutzer, der den Schlüssel (von K Bits) zur Verschlüsselung nicht kennt, weist ein perfekter N-Bit-Verschlüsselungsblock N Entropiebits für diesen Block auf.

Wenn Sie eine Million Bits pseudozufälliger Daten daraus erweitern, haben Sie immer noch nur K Entropiebits, wenn Sie mit demselben Schlüssel K weitermachen. Mit anderen Worten: Wenn Sie eine hatten Buch mit 1 Million Bits, von denen Sie wissen, dass sie mit einer einzelnen Verschlüsselung unter K generiert wurden. Versuchen Sie dann nicht, alle Verschlüsselungsdatenbits zu erraten. Halten Sie sich einfach an das Erraten des Schlüssels und generieren Sie den Chiffrestream daraus.

Ein Zufallszahlengenerator ist also oft eine Chiffre, die immer wieder mit mehr Zufälligkeit neu ausgesät wird, wie es möglich ist. Im Vergleich dazu kann ein einfacher [0,1] Zufallszahlengenerator nicht mehr Entropie haben als die Anzahl der Bits in der Zahl. und hat normalerweise eine ungerade Verteilung, die nicht genau das ist, was Sie auch wollen. Krypto benötigt Hunderte von Bits, wenn Gleitkommazahlen nur 32 oder 64 Bit sind, und der Algorithmus selbst nimmt einen Großteil der Entropie weg ... vorausgesetzt, Sie möchten etwas, das gleichmäßig von [0..1] verteilt ist, anstatt a zu sagen Gleitkomma-Darstellung aus zufälligen Bits. Ich weiß nicht einmal, welche Verteilung das überhaupt haben würde.

richzilla
2018-03-15 16:39:06 UTC
view on stackexchange narkive permalink

Sie haben die Frage irgendwie selbst beantwortet:

Der Standard gibt ausdrücklich keine Garantie für die Eignung für die kryptografische Verwendung.

Anstatt die Implementierung zu ändern, Der Schwerpunkt sollte auf der Schulung der Entwickler zur Auswahl des „richtigen Tools für den Job“ ™ liegen.

Angesichts dessen und des technischen Aufwands bei der Änderung der Implementierung einer häufig verwendeten Funktion sowie der Tatsache, dass es solche gibt Es gibt bereits zwingende Lösungen für dieses Problem (siehe Antwort von @Philipps). Es gibt keinen zwingenden Grund, die Änderung vorzunehmen.

Warum der DV?Anonyme Abstimmungen nützen niemandem ...
Ich habe abgelehnt, weil dies eine andere Frage beantwortet.Natürlich garantiert der Standard keine kryptografische Sicherheit.Meine Frage betraf jedoch speziell die opportunistische Sicherheit.Die Standards müssten nicht berührt werden.Der technische Aufwand sollte gering sein, da der Browser bereits eine Verknüpfung zu einer TLS-Bibliothek herstellt.Ich könnte wahrscheinlich einen Browser bearbeiten, um die Bibliothek für "Math.random ()" in diff in weniger als 5 Zeilen zu verwenden.
allo
2018-03-15 15:10:49 UTC
view on stackexchange narkive permalink

Das Design von Programmiersprachen muss viele Dinge berücksichtigen. Browser sind sehr leistungsfähig und optimieren Javascript heute sehr. Wenn Sie jedoch eingebettete Systeme in Betracht ziehen, haben Sie möglicherweise keine gute Zufallsquelle. Zum Beispiel gibt es Mikrocontroller, die eine NodeJS (ähnliche) Umgebung ausführen.

Ein solcher Mikrocontroller verfügt nicht über zufällige Quellen, die kryptografisch sichere Zufallszahlen garantieren. Sie müssten also ein Gerät anschließen, das eine zufällige Eingabe an einen Pin liefern kann, um eine Programmiersprache implementieren zu können, die starke Garantien für Zufallszahlen bietet. Und Sie benötigen einige Kenntnisse, um ein Gerät zu erstellen, das genügend Zufälligkeit bietet, und um die Eingaben vom Gerät auf geeignete Weise zu verarbeiten.

Ein Browser, in dem JavaScript ausgeführt wird, verfügt normalerweise über eine gute Zufallsquelle, um TLS bereitzustellen.Und wie gesagt, der Standard müsste nicht geändert werden, es muss keine Garantie dafür geben, dass die API eine kryptografisch sichere Zufälligkeit ausgibt.
Wenn die API keine echte Zufälligkeit garantiert, sollten Sie sich als Entwickler nicht darauf verlassen.Wenn sich die Entwickler nicht darauf verlassen, müssen Sie es nicht implementieren.Stellen Sie sich vor, die meisten Browser hätten dort echte Zufälligkeit.Websites würden darauf aufbauen, weil es da ist.Und dann hat der nächste Browser keine echte Zufälligkeit.Hoppla.Ein weiterer Grund kann sein, dass Sie den Entropiepool mehr erschöpfen und mehr Zeit benötigen, wenn Sie in jedem API-Aufruf echte Zufallswerte ausgeben, für die diese nicht erforderlich sind.
Aber einige Entwickler verlassen sich darauf, nicht weil sie denken, dass es kryptografisch sicher ist, sondern weil sie nicht wissen, wie Zufälligkeit funktioniert.Es gibt auch keine "anstrengende Entropie".Ein einzelner 128-Bit-Startwert kann eine effektiv unbegrenzte Menge unvorhersehbarer Daten ausgeben.
@forest Zwar kann ein ausreichend zufälliger 128-Bit-Schlüssel in Kombination mit ausreichend guten kryptografischen Grundelementen kryptografisch sicherere pseudozufällige Daten erzeugen, als irgendjemand in unserem Leben wahrscheinlich benötigt, aber es gibt viele Einschränkungen.Die einfache Tatsache ist, dass in einigen CSPRNG-Implementierungen, einschließlich vieler Linux-Kernel, Entropiepools * keine * unbegrenzte Ressource sind und erschöpft / erschöpft werden können, wenn Sie sie stark genug abfragen.Ermutigen Sie die Leute, Dinge wie "/ dev / urandom" und nicht "/ dev / random" zu verwenden, wenn Sie möchten, aber tun Sie nicht so, als ob "/ dev / random" nicht ausgehen kann.
@CBHacking Sie sind tatsächlich unbegrenzt.Und tatsächlich läuft "/ dev / random" nie "aus".Vielmehr blockiert es absichtlich aus ziemlich dummen Gründen.Lesen Sie den Code unter [`drivers / char / random.c`] (https://github.com/torvalds/linux/blob/master/drivers/char/random.c), um dies genauer zu verstehen (es ist buchstäblich einRufen Sie `wait_event_interruptible ()` für die geschätzte Anzahl auf.Solange ChaCha20 (das `/ dev / urandom` verwendet) nicht in vielerlei Hinsicht tödlich zerstört wird, gibt es keinen Grund, den Blockierungspool über dem nicht blockierenden Pool zu verwenden.Beachten Sie, dass Browser den Blockierungspool nicht verwenden.
@forest Pedantry wird nicht zu dir.Der Entropiepool füllt sich selbst wieder auf, aber zu behaupten, dass er "nie ausgeht", ist wie zu sagen, dass mir die Milch nicht "ausgehen" kann, solange es ein erreichbares Lebensmittelgeschäft gibt.In ähnlicher Weise ist die Behauptung, dass die Gründe, aus denen "/ dev / random" blockiert werden kann, "albern" sind und "Legacy" nichts an der Tatsache ändert, dass Lesevorgänge für beliebig lange Zeit blockiert werden können, und dies wurde tatsächlich bei Dingen wie VMs beobachtetohne Benutzerinteraktion oder echte Hardware (obwohl der Host heutzutage häufig Entropie in die VM einspeist).Ist für Browser die nicht blockierende Entropiequelle für eine Spezifikation erforderlich?
@CBHacking Wenn Sie Milch trinken, verschwindet die Milch aus dem Krug.Wenn Sie Entropie verwenden, sind die Pooldaten auch aus dem blockierenden Pool noch vorhanden.Das einzige, was sich ändert, ist eine einzelne ganze Zahl, die eine Schätzung der Entropie verfolgt.Für Browser ist dies erforderlich.Viele Operationen, die einen unvorhersehbaren Strom von Zufallszahlen erfordern, müssen innerhalb eines bestimmten Zeitraums gemäß den Spezifikationen ausgeführt werden.Eine TCP-Implementierung, bei der das Risiko besteht, auf unbestimmte Zeit auf die Zufälligkeit der Sequenznummer zu warten, wäre eine fehlerhafte Implementierung.
Wenn Sie den Kernel patchen würden, um das Blockierungsverhalten von "/ dev / random" mit Gewalt zu entfernen, würde er nicht ersticken oder sich in "/ dev / zero" verwandeln, wie Sie es erwarten würden, wenn die Entropie tatsächlich aufgebraucht wäre.Es wäre immer noch ein perfekt sicheres CSPRNG, wenn auch eines, das auf dem Vorbildwiderstand von SHA1 beruht (der Blockierungspool und der versteckte Eingabepool verwenden SHA1-Mischen, während ein moderner nicht blockierender Pool ChaCha20 verwendet, das mit 48 Bytes zufälliger Daten aus der Eingabe geimpft istSchwimmbad).Ich nehme an, Sie können den Begriff "läuft aus" verwenden, aber nur in einem sehr liberalen Sinne.Es ist technisch ungenau und fördert Mythen.
@forest Fair genug, aber das Verhalten ähnelt immer noch dem "Auslaufen" der Entropie einer Client-Anwendung, und ich würde nicht damit rechnen, dass der Vorbildwiderstand von SHA1 zu lange anhält. Zu diesem Zeitpunkt ist ein nicht blockierendes `/ dev / random`wäre kein" perfekt sicheres CSPRNG "mehr.Bei Browsern habe ich über die JS-API gesprochen, nicht über das, was der Kernel-Netzwerkstapel (nicht der Browser!) Mit TCP-Sequenznummern macht.Offensichtlich würde der Browser für diese Frage "Math.random ()" nicht mithilfe des Blockierungspools implementieren, sondern nur, weil dies dumm und nicht unmöglich wäre.
@CBHacking Die Art und Weise, wie SHA1 im Zufallstreiber verwendet wird, besteht einfach darin, die Daten zu mischen und den gesamten 4096-Bit-Puffer zu hashen.Ein Vorbild gegen SHA1, wie es im Kernel verwendet wird, wäre ... sehr unerwartet (ich würde wetten, dass ChaCha20 vorher kaputt sein wird).Was die JS-Spezifikationen betrifft, weiß ich nicht.Es gibt wahrscheinlich keine wirklichen Anforderungen an die kryptografische Zufälligkeit, aber ich bin sicher, dass dies für nicht blockierendes Verhalten der Fall ist.Der Punkt ist, dass alles, was es braucht, 128 Bit Zufälligkeit sind, um "Math.random ()" opportunistisch sicher zu machen, ohne diesen Teil des Standards zu machen.
Der Punkt ist, dass Sie, wenn der Status Ihres CSPRNG leckt, Entropie benötigen, um ihn wieder auf einen zufälligen Wert zu setzen.Und wenn Sie sich jetzt Ihren Mikrocontroller ansehen, ist er sehr deterministisch.Sein Speicher sieht nach dem Booten immer gleich aus, je nachdem, welcher Chip an dem Punkt, an dem die Zufallszahl angefordert wird, sogar die gleiche Anzahl von Taktzyklen hatte.Sie müssen es also setzen, sonst ist Ihre zufällige Reihenfolge immer dieselbe.
Und mit zu wenig Entropie kann jemand den Zustand Ihres CSPRNG mithilfe von Brute-Force anhand der Zufallssequenz zur Validierung ermitteln, wenn Sie ihn nicht oft genug aussäen.Beachten Sie, dass nicht nur der Status des MC sehr begrenzt ist, sondern das Programm selbst nicht zu komplex sein kann, da nur wenig Platz für Ihr Programm vorhanden ist und Sie wahrscheinlich das meiste davon für den Rest Ihres Codes benötigen.
Wenn Sie "getrandom ()" verwenden, wird es erst zurückgegeben, wenn der Entropiepool initialisiert wurde.Sobald dies erledigt ist, können Sie sicher sein, dass der Pool nicht brutal gezwungen werden kann.
@forest Wir sprechen hier nicht über Linux.Ihr Mikrocontroller mit einer einfachen Javascript-Implementierung verfügt überhaupt nicht über einen Kernel (im Sinne eines Linux-Kernels).Es bootet direkt in seine nodejs (like) -Umgebung, die keinen `` getrandom () `` -Aufruf hat.Sie müssten den Aufruf mit allen genannten Überlegungen selbst implementieren.
In diesem Fall können Sie einfach auf das gewünschte beschissene PRNG zurückgreifen (XorShift128 +, LFSR, LCG, was auch immer).Sie müssen den Standard nicht ändern, um opportunistische Sicherheit auf einer Plattform zu bieten.
Cort Ammon
2018-03-17 03:04:51 UTC
view on stackexchange narkive permalink

Wie andere möchte ich darauf hinweisen, dass Math.random () nicht kryptografisch sicher ist, da es normalerweise nicht benötigt wird. Aber ich würde noch weiter gehen und argumentieren, dass es nicht ratsam ist, einen kryptografisch sicheren Algorithmus in eine Spezifikation zu schreiben, es sei denn, Sie haben einen sehr guten Grund.

Was bedeutet es, kryptografisch sicher zu sein? Nun, es gibt immer die langweilige Definition von "Niemand weiß, wie man es noch bricht". Aber was passiert, wenn jemand es kaputt macht? Wenn Sie ein CSPRNG angegeben haben, müssen Sie auch eine Möglichkeit angeben, um abzufragen, welcher Algorithmus verwendet wird, oder auf andere Weise festlegen, dass der Endbenutzer sicher sein kann, was er erhält.

Dies ist ebenfalls wahrscheinlich Dies führt dazu, dass mehrere Generatoren unterstützt werden müssen, damit der Benutzer einen auswählen kann, dem er vertraut. Dies erhöht die Komplexität erheblich. Plötzlich wurde eine 1-Zeilen-Funktion in einer API zu einer Suite.

Wenn Sie anfangen, über Krypto zu sprechen, sprechen Sie auch über den Versuch, im Generator sicher zu sein. Sie erwähnen die Verwendung von AES zur Generierung von Zufallszahlen: Muss Ihre AES-Implementierung gegen Seitenkanalangriffe immun sein? Wenn Sie eine Bibliothek mit dem speziellen Zweck schreiben, kryptografische Garantien bereitzustellen, ist es nicht allzu unvernünftig, diese Frage stellen zu müssen. Für eine Spezifikation könnte es schrecklich unvernünftig sein. Die Immunität gegen Seitenkanalangriffe ist in der Sprache der Spezifikationen sehr schwer zu formulieren.

Und was haben Sie erreicht, indem Sie es in eine Spezifikation aufgenommen haben? Die meisten Benutzer von PRNGs benötigen überhaupt keine kryptografischen Garantien, sodass Sie nur CPU-Zyklen für sie verschwendet haben. Diejenigen, die kryptografische Garantien wünschen, werden wahrscheinlich eine Bibliothek suchen, die die gesamte Funktionalität unterstützt, die erforderlich ist, um mit einer solchen Kryptografie vertraut zu sein, sodass sie Math.random () sowieso nicht vertrauen. Alles, was übrig bleibt, ist die von Ihnen erwähnte Bevölkerungsgruppe: Menschen, die einen Fehler gemacht und ein Werkzeug verwendet haben, wenn sie es nicht sollten. Nun, ich kann Ihnen aus Erfahrung sagen, dass wichtige Programmiersprachen kein Ort sind, um nach einer API zu suchen, die Sie nicht versehentlich falsch verwenden können. Sie sind voll von Formulierungen "Wenn Sie dies tun, ist es Ihre eigene Schuld".

Beachten Sie auch Folgendes: Wenn Sie Math.random () verwenden und kryptografische Garantien übernehmen, Wie hoch ist die Wahrscheinlichkeit, dass Sie irgendwo in Ihrem Algorithmus einen weiteren schwerwiegenden Kryptofehler machen? Ein CSPRNG Math.random () kann ein falsches Sicherheitsgefühl vermitteln, und wir finden möglicherweise noch mehr Fehler!

Offensichtlich sollten Sie keine _assume_ kryptografischen Eigenschaften verwenden.Wenn Sie das brauchen, gibt es dedizierte Krypto-APIs (deshalb habe ich auch ChaCha8 anstelle des vollständigen ChaCha20 vorgeschlagen. Beachten Sie, dass eine kryptografische Unterbrechung gegen ein 7-Runden-ChaCha durchgeführt werden kann).
Siehe meine Bearbeitung der ursprünglichen Frage, die dies verdeutlicht.
@forest Ich sehe Ihre Bearbeitung, und ich denke, mein letzter Absatz gilt noch.Wenn man denkt, dass ihre Software sicher ist, weil sie Glück hatten und jemand anderes über Sicherheit für sie nachdachte, steht ihnen ein unhöfliches Erwachen bevor.
Spence
2018-03-22 18:51:10 UTC
view on stackexchange narkive permalink

Jeder scheint hier eine Nuance übersehen zu haben: Kryptografische Algorithmen erfordern, dass eine Zahl über alle Ausführungen des Algorithmus mathematisch und statistisch zufällig ist. Dies bedeutet zum Beispiel während eines Spiels oder einer Animation, dass Sie eine pseudozufällige Folge von Zahlen verwenden könnten, und dies wäre für eine "Art von Zufallszahl" vollkommen in Ordnung.

Wenn diese Zahl jedoch manipuliert werden könnte oder vorhergesagt, zum Beispiel eine gesetzte Zufallszahl (was das Standardverhalten der Windows-Zufallsfunktionen ist), dann ist dieser Start tatsächlich vorhersehbar. Wenn ich Ihre Anwendung manipulieren kann, um neu zu starten und dann eine gesetzte Zufallszahl zu verwenden, kann ich vorhersagen, welche "Zufallszahl" Sie wählen werden. Wenn dies möglich ist, kann die Kryptographie besiegt werden. Ein sekundäres Problem kann auch sein, dass einige Algorithmen eine garantierte Verteilung von Zahlen über das Spektrum erfordern, die bestimmte Pseudozufallsgeneratoren nicht garantieren können.

Kryptografisch zufällige Zahlengeneratoren verfügen über eine große Anzahl von Eingaben, um Entropie zu erzeugen, beispielsweise zum Messen Schussgeräusche vom Mikrofoneingang, Tageszeit-Ticks, Prüfsumme der RAM-Register, Seriennummern usw. So viele Eingänge wie möglich, um es unmöglich zu machen, dann unglaublich schwer zu manipulieren und vorherzusagen. In einem kryptografischen Sinne ist Leistung nicht das Ziel, sondern "wahre" Zufälligkeit.

Abhängig von Ihrem Anwendungsfall möchten Sie möglicherweise eine einigermaßen zufällige, performante Implementierung einer Zufallszahl, aber wenn Sie einen Unterschied machen -Hellman-Schlüsselaustausch Sie benötigen einen kryptografisch sicheren Algorithmus.

Bobby Baucom
2018-03-24 04:02:59 UTC
view on stackexchange narkive permalink

Eine weitere Überlegung, die ich nicht erwähnt habe (oder die ich einfach übersehen habe), ist, dass einige Verwendungen der Funktion Math.random () tatsächlich von der Wiederholbarkeit abhängen, wenn sie wie zuvor gesetzt wurden Zeit. Wenn Sie es jetzt ändern, werden diese Verwendungen unterbrochen.

Alle deterministischen PRNGs tun dies, kryptografisch sicher oder nicht.
Welche Browser wurden mit der Möglichkeit ausgeliefert, den Generator zu setzen?


Diese Fragen und Antworten wurden automatisch aus der englischen Sprache übersetzt.Der ursprüngliche Inhalt ist auf stackexchange verfügbar. Wir danken ihm für die cc by-sa 3.0-Lizenz, unter der er vertrieben wird.
Loading...