Wie verwende ich Node.js Crypto, um einen HMAC-SHA1-Hash zu erstellen?

198

Ich möchte einen Hash von I love cupcakes(mit dem Schlüssel signiert abcdeg) erstellen.

Wie kann ich diesen Hash mit Node.js Crypto erstellen?

user847495
quelle

Antworten:

366

Dokumentation für Krypto: http://nodejs.org/api/crypto.html

const crypto = require('crypto')

const text = 'I love cupcakes'
const key = 'abcdeg'

crypto.createHmac('sha1', key)
  .update(text)
  .digest('hex')
Ricardo Tomasi
quelle
'hex' wird nicht immer benötigt, zum Beispiel für das hmac Digest-Äquivalent von Rubin.
Htafoya
6
Und um einen Hash zu überprüfen, sollten Sie verwenden crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b)): stackoverflow.com/questions/31095905/…
Taufe
1
Der Kreis schließt sich: nodejs.org/api/crypto.html#crypto_crypto
Ricardo Tomasi
98

Vor ein paar Jahren hieß es, dass update()und digest()Legacy - Methoden und die neue Streaming - API - Ansatz eingeführt waren. Jetzt sagen die Dokumente, dass beide Methoden verwendet werden können. Beispielsweise:

var crypto    = require('crypto');
var text      = 'I love cupcakes';
var secret    = 'abcdeg'; //make this your secret!!
var algorithm = 'sha1';   //consider using sha256
var hash, hmac;

// Method 1 - Writing to a stream
hmac = crypto.createHmac(algorithm, secret);    
hmac.write(text); // write in to the stream
hmac.end();       // can't read from the stream until you call end()
hash = hmac.read().toString('hex');    // read out hmac digest
console.log("Method 1: ", hash);

// Method 2 - Using update and digest:
hmac = crypto.createHmac(algorithm, secret);
hmac.update(text);
hash = hmac.digest('hex');
console.log("Method 2: ", hash);

Getestet auf Knoten v6.2.2 und v7.7.2

Siehe https://nodejs.org/api/crypto.html#crypto_class_hmac . Gibt weitere Beispiele für die Verwendung des Streaming-Ansatzes.

Adam Griffiths
quelle
Kein Einzeiler, und Anrufe können nicht verkettet werden ... aber ich werde diesen Ansatz verwenden.
tfmontague
2
Ich kann diese Arbeit für mein Leben nicht schaffen. hmac.read () gibt ein "[Objekt SlowBuffer]" zurück und wenn ich versuche, den Inhalt mit hmac.read () zu lesen. toString ('hex'); Ich bekomme nicht den erwarteten Wert. Wenn ich den veralteten Update / Digest-Ansatz verwende, wird die erwartete Zeichenfolge zurückgegeben. Ich verwende dies, um eine Signatur von einem POST eines Drittanbieters auf meinen Servern zu validieren. Irgendwelche Ideen, was los ist?
AngraX
Vielleicht passiert das hmac.read, bevor die Daten in den Stream geleert wurden? Vielleicht sollte hmac.read vom Finish-Event des Streams gesteuert werden?
Dave
Tatsächlich erwähnt der Link, den Sie gepostet haben, ausdrücklich die Verwendung von updateund nicht write. Ich bin verwirrt, was ist jetzt die beste Vorgehensweise? Ich kann keine Ressourcen finden, die das so deutlich sagen, wie Sie es erwähnen.
SCBuergel.eth
5
Stand November 2016 digestund updatesind nicht veraltet und werden in der Dokumentation vorgestellt: nodejs.org/api/crypto.html#crypto_class_hmac . Ich empfehle, die Stream-API nur zu verwenden, wenn Sie aus einem Stream lesen.
Ricardo Tomasi
22

Die Lösung von Gwerder funktioniert nicht, da hash = hmac.read();dies geschieht, bevor der Stream fertiggestellt ist. Also die Probleme von AngraX. Auch derhmac.write Anweisung ist in diesem Beispiel nicht erforderlich.

Tun Sie stattdessen Folgendes:

var crypto    = require('crypto');
var hmac;
var algorithm = 'sha1';
var key       = 'abcdeg';
var text      = 'I love cupcakes';
var hash;

hmac = crypto.createHmac(algorithm, key);

// readout format:
hmac.setEncoding('hex');
//or also commonly: hmac.setEncoding('base64');

// callback is attached as listener to stream's finish event:
hmac.end(text, function () {
    hash = hmac.read();
    //...do something with the hash...
});

Formaler, wenn Sie möchten, die Linie

hmac.end(text, function () {

könnte geschrieben werden

hmac.end(text, 'utf8', function () {

weil in diesem Beispiel Text eine utf-Zeichenfolge ist

Dave
quelle
Sie liegen falsch, es ist nicht erforderlich, einen Rückruf hinzuzufügen. Dieser Stream ist synchron und kann direkt nach dem Aufruf von end () gelesen werden. Das Faszinierendste ist, dass es in der offiziellen Dokumentation geschrieben ist, aber jeder muss seine 5 (verbogenen) Cent
eingeben
Trollst du Vielleicht sollten Sie die Dokumentation lesen. Wenn Sie versuchen, den Stream vor dem Endereignis zu lesen, schlägt dies fehl.
Dave
1
Von [ nodejs.org/api/crypto.html#crypto_class_hmac] It is a stream that is both readable and writable. The written data is used to compute the hmac. Once the writable side of the stream is ended, use the read() method to get the computed digest. Sie lesen es, wenn die beschreibbare Seite beendet ist. Sie müssen nicht einmal warten, bis die lesbare Seite lesbar wird (obwohl dies sicherlich der Fall ist). Lesen Sie bitte Ihre Dokumentation.
Stroncium
createHmac erstellt einen Stream . " beendet " in der oben zitierten Dokumentationszeile bedeutet nicht, dass hmac.end(...)aufgerufen wurde. " beendet " bedeutet, dass der Stream sein Endereignis ausgelöst hat , weshalb der Befehl einen Rückruf akzeptiert. Nach dem Aufruf der end () -Methode benötigt der Stream Zeit, um die Daten auf das zugrunde liegende System zu übertragen. Wenn Sie read () aufrufen, bevor das Finish-Ereignis ausgelöst wird, schlägt dies fehl. Geben Sie Gwerders Code in JSbin ein und überzeugen Sie sich selbst. Sie sollten die Streams- Dokumentation lesen, um zu verstehen, wie es funktioniert.
Dave
Ich habe es für einige Zeit im Produktionscode verwendet und es ist höllisch stabil. Ich weiß ehrlich gesagt nicht, was JSBin ist, aber ich habe auch den unterstützten Code in nodejs mit nur Kopieren und Einfügen ausprobiert und es funktioniert auch. Sie sollten sich keine zusätzlichen Bedeutungen für die Dokumentation vorstellen. "beendet" bedeutet immer "beendet" überall in der Dokumentation. Wieder einmal scheinen Sie falsch zu verstehen, dass Stream zwei Seiten hat. In der Dokumentation wird ausdrücklich angegeben, dass die Person verwenden kann, read()wenn die beschreibbare Seite endet, und es gibt nichts über das Ende des Ereignisses.
Stroncium