Comment utiliser Node.js Crypto pour créer un hachage HMAC-SHA1?

198

Je veux créer un hachage de I love cupcakes(signé avec la clé abcdeg)

Comment puis-je créer ce hachage à l'aide de Node.js Crypto?

user847495
la source

Réponses:

366

Documentation pour 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')
Ricardo Tomasi
la source
'hex' n'est pas toujours nécessaire, par exemple pour faire l'équivalent hmac digest de rubis.
htafoya
6
Et pour vérifier un hachage, vous devez utiliser crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b)): stackoverflow.com/questions/31095905/…
baptx
1
Le cercle est bouclé: nodejs.org/api/crypto.html#crypto_crypto
Ricardo Tomasi
98

Il y a quelques années, il a été dit que update()et digest()étaient des méthodes héritées et la nouvelle approche API de streaming a été introduite. Maintenant, les documents indiquent que l'une ou l'autre méthode peut être utilisée. Par exemple:

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

Testé sur les nœuds v6.2.2 et v7.7.2

Voir https://nodejs.org/api/crypto.html#crypto_class_hmac . Donne plus d'exemples d'utilisation de l'approche de streaming.

Adam Griffiths
la source
Pas une ligne, et les appels ne peuvent pas être connectés en guirlande ... mais je vais utiliser cette approche.
tfmontague
2
Je ne peux pas, pour la vie de moi, faire fonctionner ça. hmac.read () renvoie un "[object SlowBuffer]" et si j'essaie de lire le contenu en utilisant hmac.read (). toString ('hex'); Je n'obtiens pas la valeur attendue. Si j'utilise l'approche obsolète update / digest, elle renvoie la chaîne attendue. J'utilise ceci pour valider une signature d'un POST tiers sur mes serveurs. Une idée de ce qui se passe?
AngraX
Peut-être que hmac.read se produit avant que les données aient été vidées dans le flux? Peut-être que hmac.read devrait être motivé par l'événement d'arrivée du flux?
Dave
En fait, le lien que vous avez publié mentionne explicitement l'utilisation updateet non write. Je suis confus, quelle est la meilleure pratique maintenant? Je ne trouve pas de ressources qui le disent aussi clairement que vous le mentionnez.
SCBuergel.eth
5
A partir de novembre 2016, digestet updateont pas été dépréciée et sont présentés dans la documentation: nodejs.org/api/crypto.html#crypto_class_hmac . Je recommande d'utiliser l'API de flux uniquement si vous lisez à partir d'un flux.
Ricardo Tomasi
22

La solution de Gwerder ne fonctionnera pas car elle hash = hmac.read();se produit avant la finalisation du flux. D'où les problèmes d'AngraX. De plus, l' hmac.writeinstruction n'est pas nécessaire dans cet exemple.

Au lieu de cela, procédez comme suit:

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

Plus formellement, si vous le souhaitez, la ligne

hmac.end(text, function () {

pourrait être écrit

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

parce que dans cet exemple, le texte est une chaîne utf

Dave
la source
Vous vous trompez, il n'est pas nécessaire d'ajouter un rappel. Ce flux est synchrone et est lisible juste après l'appel de end (). Le plus fascinant, c'est qu'il est écrit dans la documentation officielle, mais tout le monde doit y mettre 5 cents (courbés).
stroncium
Êtes-vous à la traîne? Vous devriez peut-être lire la documentation. Si vous essayez de lire le flux avant l'événement de fin, il échouera.
Dave
1
De [ 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. Vous le lisez lorsque le côté accessible en écriture est terminé , vous n'avez même pas besoin d'attendre quand le côté accessible en lecture devient lisible (bien que ce soit sûrement le cas). Lisez votre documentation s'il vous plaît.
stroncium
createHmac crée un flux . « terminé » dans la ligne de documentation que vous citez ci-dessus ne signifie pas qu'il hmac.end(...)a été appelé, « terminé » signifie que le flux a déclenché son événement de fin , c'est pourquoi la commande accepte un rappel. Après l'appel de la méthode end (), le flux nécessite du temps pour vider les données vers le système sous-jacent. Si vous appelez read () avant que l'événement de fin ne soit déclenché, il échouera. Allez-y et passez le code de Gwerder dans JSbin et voyez par vous-même. Vous devriez lire la documentation Streams pour comprendre comment cela fonctionne.
Dave
Je l'ai utilisé dans le code de production depuis un certain temps et il est stable comme l'enfer. Honnêtement, je ne sais pas ce qu'est JSBin, mais j'ai également essayé le code pris en charge dans nodejs avec juste un copier-coller et cela fonctionne aussi. Vous ne devriez pas imaginer des significations supplémentaires pour la documentation. "terminé" signifie toujours "terminé" partout dans la documentation. Encore une fois, vous semblez mal comprendre que le flux a 2 côtés. Et dans la documentation, il est explicitement indiqué que la personne peut utiliser read()lorsque le côté accessible en écriture est terminé, et il n'y a rien à propos de l'événement de fin.
stroncium