Come uso Node.js Crypto per creare un hash HMAC-SHA1?


Risposte:


366

Documentazione per crypto: 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')

'hex' non è sempre necessario, ad esempio per fare l'equivalente digest hmac del rubino.
htafoya,

6
E per verificare un hash, si dovrebbe usare crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b)): stackoverflow.com/questions/31095905/...
baptx


98

Qualche anno fa si diceva che update()e digest()erano metodi legacy e è stato introdotto il nuovo approccio di streaming API. Ora i documenti dicono che è possibile utilizzare entrambi i metodi. Per esempio:

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);

Testato sul nodo v6.2.2 e v7.7.2

Vedi https://nodejs.org/api/crypto.html#crypto_class_hmac . Fornisce ulteriori esempi per l'utilizzo dell'approccio di streaming.


Non un one-liner, e le chiamate non possono essere concatenate ... ma userò questo approccio.
tfmontague,

2
Per la mia vita, non posso farlo funzionare. hmac.read () restituisce un "[oggetto SlowBuffer]" e se provo a leggere il contenuto usando hmac.read (). toString ('hex'); Non ottengo il valore atteso. Se uso l'approccio obsoleto update / digest, restituisce la stringa prevista. Sto usando questo per convalidare una firma da un POST di terze parti sui miei server. Qualche idea su cosa sta succedendo?
AngraX,

Forse hmac.read sta accadendo prima che i dati siano stati scaricati nello stream? Forse hmac.read dovrebbe essere guidato dall'evento finale del flusso?
Dave,

In realtà il link che hai pubblicato menziona esplicitamente l'uso updatee non write. Sono confuso, qual è la migliore pratica ora? Non riesco a trovare risorse che lo diano chiaramente come lo dici tu.
SCBuergel.eth,

5
A partire dal novembre 2016, digeste updatesono non è stato deprecato e sono presenti nella documentazione: nodejs.org/api/crypto.html#crypto_class_hmac . Consiglio di utilizzare l'API dello stream solo se stai leggendo da uno stream.
Ricardo Tomasi,

22

La soluzione di Gwerder non funzionerà perché si hash = hmac.read();verifica prima della finalizzazione del flusso. Quindi i problemi di AngraX. Anche la hmac.writedichiarazione non è necessaria in questo esempio.

Invece fai questo:

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...
});

Più formalmente, se lo desideri, la linea

hmac.end(text, function () {

potrebbe essere scritto

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

perché in questo esempio il testo è una stringa utf


Ti sbagli, non è necessario aggiungere un callback. Questo flusso è sincrono ed è leggibile subito dopo aver chiamato end (). La cosa più affascinante è che è scritto nella documentazione ufficiale, ma tutti devono mettere i loro 5 centesimi (piegati).
stroncium

Stai trollando? Forse dovresti leggere la documentazione. Se provi a leggere lo stream prima dell'evento finish, fallirà.
Dave,

1
Da [ 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. Lo si legge quando scrivibile lato si è conclusa , non è necessario attendere anche per quando leggibile lato diventa leggibile (anche se lo fa sicuramente). Leggi la tua documentazione per favore.
stroncium

createHmac crea un flusso . " terminato " nella riga della documentazione citata sopra non significa che hmac.end(...)sia stato chiamato, " terminato " significa che il flusso ha generato il suo evento di fine , motivo per cui il comando accetta un callback. Dopo aver chiamato il metodo end (), il flusso richiede tempo per scaricare i dati nel sistema sottostante. Se si chiama read () prima che venga generato l'evento di fine, non riuscirà. Vai avanti e inserisci il codice di Gwerder in JSbin e vedi di persona. Dovresti leggere la documentazione di Stream per capire come funziona.
Dave,

L'ho usato nel codice di produzione per qualche tempo ed è stabile da morire. Onestamente non so cosa sia JSBin, ma ho anche provato il codice supportato in nodejs con solo copia-incolla e funziona anche. Non dovresti immaginare significati aggiuntivi alla documentazione. "finito" significa sempre "finito" ovunque nella documentazione. Ancora una volta, sembra che tu abbia frainteso che lo stream ha 2 lati. E nella documentazione si afferma esplicitamente che la persona può usare read()quando finisce il lato scrivibile e non c'è nulla sull'evento finish.
Stroncium
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.