Wie kann ich den sha1-Hash eines Strings in node.js abrufen?

108

Ich versuche, einen in node.js geschriebenen Websocket-Server zu erstellen

Damit der Server funktioniert, muss der SHA1-Hash eines Strings abgerufen werden.

Was ich tun muss, wird in Abschnitt 5.2.2, Seite 35 der Dokumentation erläutert .

ANMERKUNG: Wenn beispielsweise der Wert des "Sec-WebSocket-Key" Headers im Handshake des Clients "dGhlIHNhbXBsZSBub25jZQ=="wäre, würde der Server "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"den String anhängen , um die Zeichenfolge zu bilden "dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11". Der Server würde dann den SHA-1-Hash dieser Zeichenfolge nehmen und den Wert 0xb3 0x7a 0x4f 0x2c 0xc0 0x62 0x4f 0x16 0x90 0xf6 0x46 0x06 0xcf 0x38 0x59 0x45 0xb2 0xbe 0xc4 0xea geben. Dieser Wert wird dann base64-codiert, um den Wert anzugeben "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", der im "Sec-WebSocket-Accept"Header zurückgegeben wird.

Eric
quelle
9
Ich würde sehr empfehlen , die hervorragende Verwendung socket.io Bibliothek stattdessen Ihre eigene Walz. Dies wurde nicht nur ausgiebig getestet und gepatcht, sondern unterstützt auch die meisten Browser (Ereignisse ohne die WebSocket-API) mit verschiedenen Methoden.
Alex Turpin
1
Eine gute Referenz für die zukünftigen Besucher: stackoverflow.com/questions/9407892/…
Damodaran

Antworten:

32

Obligatorisch: SHA1 ist defekt , Sie können SHA1-Kollisionen für 45.000 USD berechnen . Sie sollten verwenden sha256:

var getSHA256ofJSON = function(input){
    return crypto.createHash('sha256').update(JSON.stringify(input)).digest('hex')
}

So beantworten Sie Ihre Frage und erstellen einen SHA1-Hash:

const INSECURE_ALGORITHM = 'sha1'
var getInsecureSHA1ofJSON = function(input){
    return crypto.createHash(INSECURE_ALGORITHM).update(JSON.stringify(input)).digest('hex')
}

Dann:

getSHA256ofJSON('whatever')

oder

getSHA256ofJSON(['whatever'])

oder

getSHA256ofJSON({'this':'too'})

Offizielle Knotendokumente auf crypto.createHash()

Mikemaccana
quelle
7
Gute Idee. Beachten Sie jedoch, dass alle Objekte ( mit Ausnahme von Arrays und null) den gleichen Wert sha1sum da haben Object.toString()kehrt [object Object]standardmäßig. Also sha1sum({})=== sha1sum({"foo":"bar"})=== sha1sum({"a":1})usw.
Maerics
sha1 (JSON.stringify ("ein String")) => sha1 ("ein String"), was absolut nicht erwartet wird und nicht plattformübergreifend ist. Manchmal ist der Feind des Guten besser.
Pierre
3
Es wird erwartet, dass sha1 einer bestimmten Zeichenfolge auf jeder Plattform gleich ist. Ihre Implementierung mit JSON.stringify ändert die ursprüngliche Zeichenfolge, und sha1sum ("abcd") ergibt f805c8fb0d5c466362ce9f0dc798bd5b3b32d512, wobei jeder 81fe8bfe87576c3ecb22426f8e57847382917acf
Pierre
2
@Pierre Das ist ein ausgezeichneter Punkt. Ich denke, die Benennung der Funktion sha1sumist ungenau, wenn man bedenkt, was Sie gesagt haben - dies macht eindeutig mehr als ein normaler sha1. Ich habe die Funktion in der Antwort umbenannt.
Mikemaccana
Es ist bis heute keine Kollision für den Standard 80-Runden-SHA-1 gemäß stackoverflow.com/a/3476791/1236215
kzahel
8

Bitte lesen und berücksichtigen Sie meinen Rat in den Kommentaren Ihres Beitrags. Wenn Sie dennoch einen guten Grund dafür haben, lesen Sie diese Liste der Kryptomodule für Node . Es verfügt über Module für den Umgang mit sha1 und base64.

Alex Turpin
quelle
7

Tipps zur Vermeidung von Problemen (schlechter Hash):

Ich habe erfahren, dass NodeJS die UTF-8-Darstellung des Strings hasht. Andere Sprachen (wie Python, PHP oder PERL ...) haben die Byte-Zeichenfolge gehasht.

Wir können ein binäres Argument hinzufügen , um die Byte-Zeichenfolge zu verwenden.

const crypto = require("crypto");

function sha1(data) {
    return crypto.createHash("sha1").update(data, "binary").digest("hex");
}

sha1("Your text ;)");

Sie können versuchen mit: "\ xac", "\ xd1", "\ xb9", "\ xe2", "\ xbb", "\ x93" usw.

Andere Sprachen (Python, PHP, ...):

sha1("\xac") //39527c59247a39d18ad48b9947ea738396a3bc47

Nodejs:

sha1 = crypto.createHash("sha1").update("\xac", "binary").digest("hex") //39527c59247a39d18ad48b9947ea738396a3bc47
//without:
sha1 = crypto.createHash("sha1").update("\xac").digest("hex") //f50eb35d94f1d75480496e54f4b4a472a9148752
A-312
quelle
1
'binary'- Alias ​​für 'latin1' nodejs.org/api/…
Jossef Harush
1
^^ Extrem wichtige Bemerkung dort von @JossefHarush! Wenn Sie den Text vor dem Hashing nicht speziell als latin1 codieren müssen (z. B. genau aus Gründen der Kompatibilität mit PHP) und die Möglichkeit besteht, dass Ihr Text Unicode-Symbole außerhalb des Bereichs latin1 enthält (z. B. Emoji!), Verwenden binarySie ihn nicht ! Die Verwendung von binaryoder latin1in der Codierung verliert Informationen und erhöht die Wahrscheinlichkeit von Kollisionen! Versuchen Sie das obige Snippet mit diesen beiden zum Beispiel: und
cbr
Alle Hashes werden mit Binärdaten durchgeführt. Das Problem ist, dass die anderen Sprachen, die Sie erwähnen, UTF-8 nicht verwenden, nicht umgekehrt. Dies wird sehr deutlich, wenn Sie versuchen, etwas außerhalb von Latin1 zu hashen. Insbesondere bei PHP wird die Codierung vollständig von der Quelle bestimmt, beispielsweise von der Textdatei selbst für fest codierten Text. Perl benötigt möglicherweise etwas schweres Heben, um UTF-8 zu verwenden.
Ryan Hanekamp
3

Sie können verwenden:

  const sha1 = require('sha1');
  const crypt = sha1('Text');
  console.log(crypt);

Zur Installation:

  sudo npm install -g sha1
  npm install sha1 --save
user944550
quelle
Hallo user944550, willkommen. Bitte fügen Sie weitere Informationen hinzu.
Tiago Martins Peres 4