it-swarm.com.de

Gibt es SHA-256-Javascript-Implementierungen, die allgemein als vertrauenswürdig gelten?

Ich schreibe ein Login für ein Forum und muss die Passwort-Client-Seite in Javascript vor dem Senden an den Server ansprechen. Ich habe Schwierigkeiten, herauszufinden, welcher SHA-256-Implementierung ich wirklich vertrauen kann. Ich habe erwartet, dass es eine Art autoritatives Skript gibt, das jeder verwendet, aber ich finde eine Menge verschiedener Projekte, die alle ihre eigenen Implementierungen haben.

Ich weiß, dass die Verwendung der Krypto anderer Leute immer ein Vertrauensvorschuss ist, es sei denn, Sie sind befähigt, sie selbst zu überprüfen, und dass es keine universelle Definition von "vertrauenswürdig" gibt, aber dies scheint etwas Gemeinsames und Wichtiges zu sein, das es irgendwie geben sollte Konsens darüber, was zu verwenden ist. Bin ich nur naiv?

Bearbeiten, da es viel in den Kommentaren aufkommt: Ja, wir machen auf der Serverseite wieder einen strengeren Hash. Das clientseitige Hashing ist nicht das Endergebnis, das wir in der Datenbank speichern. Das clientseitige Hashing ist, weil der menschliche Client es anfordert. Sie haben keinen bestimmten Grund dafür angegeben, wahrscheinlich mögen sie Overkill.

59
jono

Die Stanford JS Crypto Library enthält eine Implementierung von SHA-256. Während Krypto in JS nicht wirklich ein so gut untersuchter Ansatz ist wie andere Implementierungsplattformen, wird diese zumindest teilweise von Dan Boneh entwickelt, der ein etablierter und/oder etablierter ist Vertrauenswürdiger Name in der Kryptographie und bedeutet, dass das Projekt von jemandem übersehen wird, der tatsächlich weiß, was er tut. Das Projekt wird auch von NSF unterstützt.

Es lohnt sich jedoch darauf hinzuweisen ...
... Wenn Sie das Kennwort vor dem Senden auf der Clientseite hash, ist hash das Kennwort, und das ursprüngliche Kennwort ist irrelevant. Ein Angreifer muss nur den Hash abfangen, um den Benutzer zu annehmen. Wenn dieser Hash unverändert auf dem Server gespeichert ist, wird der Server das true-Passwort (den Hash) in Klartext speichern.

Ihre Sicherheit ist jetzt also schlechter, weil Sie beschlossen haben, Ihre eigenen Verbesserungen hinzuzufügen zu einem zuvor vertrauenswürdigen Schema.

77
tylerl

Die Implementierung von SHA-256 von Forge ist schnell und zuverlässig.

Um Tests für mehrere SHA-256-JavaScript-Implementierungen auszuführen, gehen Sie zu http://brillout.github.io/test-javascript-hash-implementations/ .

Die Ergebnisse auf meinem Rechner lassen vermuten, dass Schmiede die schnellste Implementierung und auch wesentlich schneller ist als die Stanford Javascript Crypto Library (sjcl), die in der akzeptierten Antwort erwähnt wird.

Forge ist 256 KB groß, aber das Extrahieren des SHA-256-Codes reduziert die Größe auf 4,5 KB, siehe https://github.com/brillout/forge-sha256

13
brillout

Auf https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest habe ich dieses Snippet gefunden, das ein internes js-Modul verwendet:

async function sha256(message) {
    // encode as UTF-8
    const msgBuffer = new TextEncoder('utf-8').encode(message);                    

    // hash the message
    const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);

    // convert ArrayBuffer to Array
    const hashArray = Array.from(new Uint8Array(hashBuffer));

    // convert bytes to hex string                  
    const hashHex = hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('');
    return hashHex;
}

Beachten Sie, dass crypto.subtle nur für https oder localhost verfügbar ist. Zum Beispiel für Ihre lokale Entwicklung mit python3 -m http.server müssen Sie diese Zeile zu Ihrem /etc/hosts: 0.0.0.0 localhost hinzufügen.

Reboot - und Sie können localhost:8000 mit dem crypto.subtle öffnen.

13

Nein, es gibt keine Möglichkeit, Browser-JavaScript zur Verbesserung der Kennwortsicherheit zu verwenden. Ich empfehle Ihnen dringend, diesen Artikel zu lesen. In Ihrem Fall ist das größte Problem das Hühnerei-Problem:

Was ist das "Chicken-Egg-Problem" bei der Bereitstellung von Javascript-Kryptographie?

Wenn Sie nicht darauf vertrauen, dass das Netzwerk ein Kennwort übermittelt, oder, schlimmer noch, nicht darauf, dass der Server Benutzergeheimnisse bewahrt, können Sie ihm nicht vertrauen, dass er Sicherheitscode übermittelt. Derselbe Angreifer, der vor der Einführung von Crypto Passwörter ausspioniert oder Tagebücher gelesen hat, entführt einfach den Crypto-Code, nachdem Sie dies getan haben.

[...]

Warum kann ich TLS/SSL nicht verwenden, um den Javascript-Verschlüsselungscode zu liefern?

Sie können. Es ist schwieriger als es sich anhört, aber Sie übertragen Javascript-Krypto sicher über SSL an einen Browser. Das Problem ist, dass Sie nach der Einrichtung eines sicheren Kanals mit SSL keine Javascript-Kryptographie mehr benötigen. Sie haben "echte" Kryptographie.

Was dazu führt:

Das Problem beim Ausführen von Krypto-Code in Javascript ist, dass praktisch jede Funktion, von der die Krypto abhängig ist, von jedem Inhalt, der zum Erstellen der Hosting-Seite verwendet wird, unbemerkt überschrieben werden kann. Die Kryptosicherheit könnte zu einem frühen Zeitpunkt im Prozess rückgängig gemacht werden (durch das Erzeugen falscher Zufallszahlen oder durch Manipulation von Konstanten und Parametern, die von Algorithmen verwendet werden) oder später (durch Zurückspulen des Schlüsselmaterials zu einem Angreifer) oder meistens wahrscheinliches Szenario - unter Umgehung der Krypto vollständig.

Es gibt keine zuverlässige Möglichkeit, dass ein Teil des Javascript-Codes seine Ausführungsumgebung überprüft. Der Krypto-Code von Javascript kann nicht fragen: "befasse ich mich wirklich mit einem Zufallszahlengenerator oder mit einem Faksimile eines von einem Angreifer bereitgestellten?" Und es kann sicherlich nicht behaupten, dass "niemand mit diesem Krypto-Geheimnis irgendetwas tun darf, außer auf eine Weise, die ich, der Autor, gutheiße". Dies sind zwei Eigenschaften, die häufig in anderen Umgebungen bereitgestellt werden, die Krypto verwenden, und sie sind in Javascript nicht möglich.

Grundsätzlich besteht das Problem darin:

  • Ihre Kunden vertrauen Ihren Servern nicht, daher möchten Sie zusätzlichen Sicherheitscode hinzufügen.
  • Dieser Sicherheitscode wird von Ihren Servern geliefert (denen, denen sie nicht vertrauen).

Oder alternativ,

  • Ihre Kunden vertrauen SSL nicht, daher möchten Sie, dass Sie zusätzlichen Sicherheitscode verwenden.
  • Dieser Sicherheitscode wird über SSL übermittelt.

Hinweis: Auch SHA-256 ist dafür nicht geeignet, da es so einfach ist, brute force nicht gesalzte, nicht-iterierte Kennwörter . Wenn Sie sich trotzdem dafür entscheiden, suchen Sie nach einer Implementierung von bcrypt , scrypt oder PBKDF2 .

10
Brendan Long

Ich fand diese Implementierung sehr einfach zu bedienen. Hat auch eine großzügige BSD-Lizenz:

jsSHA: https://github.com/Caligatio/jsSHA

Ich brauchte einen schnellen Weg, um die hexadezimale Darstellung eines SHA-256-Hashes zu erhalten. Es dauerte nur 3 Zeilen:

var sha256 = new jsSHA('SHA-256', 'TEXT');
sha256.update(some_string_variable_to_hash);
var hash = sha256.getHash("HEX");
6
cobbzilla

Für Interessenten ist dies Code zum Erstellen von SHA-256-Hash mit sjcl

import sjcl from 'sjcl'

const myString = 'Hello'
const myBitArray = sjcl.hash.sha256.hash(myString)
const myHash = sjcl.codec.hex.fromBits(myBitArray)
5
Danny Sullivan

Neben der Stanford-Bibliothek erwähnte dieser Tylerl. Ich fand jsrsasign sehr nützlich (Github Repo hier: https://github.com/kjur/jsrsasign ). Ich weiß nicht, wie genau es vertrauenswürdig ist, aber ich habe die API von SHA256, Base64, RSA, x509 usw. verwendet, und es funktioniert ziemlich gut. Tatsächlich enthält es auch die Stanford-Bibliothek.

Wenn Sie nur SHA256 möchten, könnte jsrsasign ein Overkill sein. Aber wenn Sie andere Bedürfnisse in dem verwandten Bereich haben, finde ich, dass es gut passt. 

0
Faraway