Wie generiere ich kryptografisch sichere Zufallszahlen in Javascript?
Wie generiere ich kryptografisch sichere Zufallszahlen in Javascript?
Antworten:
Sie können beispielsweise die Mausbewegung als Startwert für Zufallszahlen verwenden, die Zeit und die Mausposition jedes Mal auslesen, wenn das Ereignis "Onmousemove" eintritt, diese Daten einer Bleaching-Funktion zuführen und Sie haben einen erstklassigen Zufall zur Hand. Stellen Sie jedoch sicher, dass der Benutzer die Maus ausreichend bewegt hat, bevor Sie die Daten verwenden.
Bearbeiten: Ich habe selbst ein bisschen mit dem Konzept gespielt, indem ich einen Passwortgenerator erstellt habe. Ich würde nicht garantieren, dass meine Bleaching-Funktion einwandfrei ist, aber ich bin mir ziemlich sicher, dass es genug für den Job ist, wenn ich ständig neu gesät werde: ebusiness.hopto.org /generator.htm
Edit2: Es funktioniert jetzt irgendwie mit Smartphones, aber nur durch Deaktivieren der Touch-Funktionalität, während die Entropie erfasst wird. Android funktioniert auf andere Weise nicht richtig.
.password
span
Tags eingefügt wird , um das Kopieren / Einfügen / Bearbeiten zu vereinfachen. Wenn ich derzeit beispielsweise die generierten Zeichenfolgen kopiere und einfüge, werden sie als eine lange Zeichenfolge eingefügt.
Bei WHATWG wurde diskutiert, dies dem window.crypto-Objekt hinzuzufügen. Sie können die Diskussion lesen und den vorgeschlagenen API- und Webkit-Fehler (22049) überprüfen.
Habe gerade den folgenden Code in Chrome getestet , um ein zufälliges Byte zu erhalten:
(function(){
var buf = new Uint8Array(1);
window.crypto.getRandomValues(buf);
alert(buf[0]);
})();
window.crypto
mit window.msCrypto
.
In Ordnung, ich denke, Ihre besten Wetten sind:
window.crypto.getRandomValues ist seit einiger Zeit in Chrome und vor relativ kurzer Zeit auch in Firefox implementiert. Leider implementieren Internet Explorer 10 und früher die Funktion nicht. IE 11 hat window.msCrypto, was dasselbe bewirkt. sjcl verfügt über einen großen Zufallszahlengenerator, der aus Mausbewegungen erstellt wurde. Es besteht jedoch immer die Möglichkeit, dass sich die Maus nicht ausreichend bewegt hat, um den Generator zu erstellen, oder dass sich der Benutzer auf einem mobilen Gerät befindet, auf dem überhaupt keine Mausbewegung erfolgt. Daher empfehle ich einen Fallback-Fall, in dem Sie immer noch eine nicht sichere Zufallszahl erhalten können, wenn Sie keine andere Wahl haben. So habe ich damit umgegangen:
function GetRandomWords (wordCount) {
var randomWords;
// First we're going to try to use a built-in CSPRNG
if (window.crypto && window.crypto.getRandomValues) {
randomWords = new Int32Array(wordCount);
window.crypto.getRandomValues(randomWords);
}
// Because of course IE calls it msCrypto instead of being standard
else if (window.msCrypto && window.msCrypto.getRandomValues) {
randomWords = new Int32Array(wordCount);
window.msCrypto.getRandomValues(randomWords);
}
// So, no built-in functionality - bummer. If the user has wiggled the mouse enough,
// sjcl might help us out here
else if (sjcl.random.isReady()) {
randomWords = sjcl.random.randomWords(wordCount);
}
// Last resort - we'll use isaac.js to get a random number. It's seeded from Math.random(),
// so this isn't ideal, but it'll still greatly increase the space of guesses a hacker would
// have to make to crack the password.
else {
randomWords = [];
for (var i = 0; i < wordCount; i++) {
randomWords.push(isaac.rand());
}
}
return randomWords;
};
Sie müssen sjcl.js und isaac.js für diese Implementierung einschließen und den sjcl-Entropiekollektor starten, sobald Ihre Seite geladen ist:
sjcl.random.startCollectors();
sjcl ist BSD und GPL mit zwei Lizenzen, während isaac.js MIT ist. Daher ist es absolut sicher, beide in jedem Projekt zu verwenden. Wie in einer anderen Antwort erwähnt, ist Clipperz eine weitere Option, die jedoch aus irgendeinem bizarren Grund unter der AGPL lizenziert ist. Ich habe noch niemanden gesehen, der zu verstehen scheint, welche Auswirkungen dies auf eine JavaScript-Bibliothek hat, aber ich würde es allgemein vermeiden.
Eine Möglichkeit, den von mir veröffentlichten Code zu verbessern, besteht darin, den Status des isaac-Zufallszahlengenerators in localStorage zu speichern, damit er nicht jedes Mal neu gesetzt wird, wenn die Seite geladen wird. Isaac wird eine zufällige Sequenz erzeugen, aber für Kryptographiezwecke ist der Keim von entscheidender Bedeutung. Das Seeding mit Math.random ist schlecht, aber zumindest etwas weniger schlecht, wenn es nicht unbedingt bei jedem Laden einer Seite auftritt.
random16byteHex.advance(Math.floor(event.keyCode/4));
dazu, Zufallszahlen für einige Millisekunden weiter zu überspringen. Das würde dazu führen, dass die in dieser Browser-App verwendeten isaac-Zufälle von Benutzereingaben und der Hardware- / Browsergeschwindigkeit abhängen, was sehr schwer zu erraten ist.
touchmove
( Pull # 151 ) und devicemotion
( Pull # 79 ) gesammelt wird .
Verwenden Sie window.crypto.getRandomValues
wie folgt:
var random_num = new Uint8Array(2048 / 8); // 2048 = number length in bits
window.crypto.getRandomValues(random_num);
Dies wird in allen modernen Browsern unterstützt und verwendet den Zufallsgenerator des Betriebssystems (z /dev/urandom
. B. ). Wenn Sie IE11-Kompatibilität benötigen, müssen Sie deren vorangestellte Implementierung über verwenden var crypto = window.crypto || window.msCrypto; crypto.getRandomValues(..)
.
Beachten Sie, dass die window.crypto
API auch Schlüssel direkt generieren kann , was möglicherweise die bessere Option ist.
Verwenden Sie Krypto , um eine kryptografisch starke Zahl aus dem Bereich [0, 1)
(ähnlich Math.random()
) zu erhalten :
let random = ()=> crypto.getRandomValues(new Uint32Array(1))[0]/2**32;
console.log( random() );
Vielleicht möchten Sie http://sourceforge.net/projects/clipperzlib/ ausprobieren. Es enthält eine Implementierung von Fortuna , einem kryptografisch sicheren Zufallszahlengenerator. (Schauen Sie sich src / js / Clipperz / Crypto / PRNG.js an.) Es scheint, dass die Maus auch als Quelle der Zufälligkeit verwendet wird.
Zunächst benötigen Sie eine Entropiequelle. Zum Beispiel die Bewegung der Maus, des Passworts oder eines anderen. Aber all diese Quellen sind alles andere als zufällig und garantieren Ihnen 20 Entropiebits, selten mehr. Der nächste Schritt, den Sie ausführen müssen, ist die Verwendung des Mechanismus wie "Passwortbasiertes KDF". Dadurch wird es rechnerisch schwierig, Daten von zufälligen zu unterscheiden.
Vor vielen Jahren mussten Sie Ihren eigenen Zufallszahlengenerator implementieren und ihn mit Entropie ausstatten, die durch Mausbewegungen und Timing-Informationen gesammelt wurde. Dies war die Phlogiston-Ära der JavaScript-Kryptographie. In diesen Tagen müssen wir window.crypto
mit arbeiten.
Wenn Sie eine zufällige Ganzzahl benötigen , ist random-number-csprng eine gute Wahl. Es generiert sicher eine Reihe von zufälligen Bytes und konvertiert sie dann in eine unverzerrte zufällige Ganzzahl.
const randomInt = require("random-number-csprng");
(async function() {
let random = randomInt(10, 30);
console.log(`Your random number: ${random}`);
})();
Wenn Sie eine zufällige Gleitkommazahl benötigen, müssen Sie etwas mehr arbeiten. Im Allgemeinen ist die sichere Zufälligkeit jedoch ein ganzzahliges Problem, kein Gleitkommaproblem.