Jak użyć Crypto Node.js do utworzenia skrótu HMAC-SHA1?


Odpowiedzi:


366

Dokumentacja do kryptografii: 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” nie zawsze jest potrzebne, na przykład do wykonania odpowiednika rubinu w skrócie hmac.
htafoya

6
Aby zweryfikować skrót, należy użyć crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b)): stackoverflow.com/questions/31095905/…
baptx


98

Kilka lat temu mówiło się, że update()i digest()były starsze metody i nowe podejście Streaming API został wprowadzony. Teraz doktorzy mówią, że można zastosować dowolną metodę. Na przykład:

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

Testowane na węzłach 6.2.2 i 7.0.7

Zobacz https://nodejs.org/api/crypto.html#crypto_class_hmac . Podaje więcej przykładów użycia metody przesyłania strumieniowego.


Nie jest to jedna linijka, a połączeń nie można łączyć łańcuchowo ... ale zastosuję to podejście.
tfmontague

2
Nie mogę, dla mojego życia, sprawić, by to działało. hmac.read () zwraca „[obiekt SlowBuffer]” i jeśli spróbuję odczytać zawartość za pomocą hmac.read (). toString ('hex'); Nie otrzymuję oczekiwanej wartości. Jeśli użyję przestarzałej metody aktualizacji / podsumowania, zwraca oczekiwany ciąg. Używam tego do sprawdzania poprawności podpisu z testu POST innej firmy na moich serwerach. Jakieś pomysły, co się dzieje?
AngraX,

Być może hmac.read dzieje się, zanim dane zostaną usunięte do strumienia? Może hmac.read powinien być napędzany wydarzeniem kończącym strumień?
Dave

W rzeczywistości link, który opublikowałeś wyraźnie wspomina użycie, updatea nie użycie write. Jestem zdezorientowany, co jest teraz najlepszą praktyką? Nie mogę znaleźć zasobów, które mówią to tak jasno, jak o tym wspominasz.
SCBuergel.eth

5
Począwszy od listopada 2016 roku, digesta updatektóre nie były przestarzałe i są przedstawione w dokumentacji: nodejs.org/api/crypto.html#crypto_class_hmac . Zalecam używanie interfejsu API strumienia tylko wtedy, gdy czytasz ze strumienia.
Ricardo Tomasi,

22

Rozwiązanie Gwerdera nie zadziała, ponieważ hash = hmac.read();dzieje się to przed sfinalizowaniem strumienia. Zatem problemy AngraX. Równieżhmac.write instrukcja nie jest konieczna w tym przykładzie.

Zamiast tego zrób to:

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

Bardziej formalnie, jeśli chcesz, linia

hmac.end(text, function () {

można napisać

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

ponieważ w tym przykładzie tekst jest ciągiem utf


Mylisz się, nie ma potrzeby dodawania oddzwaniania. Ten strumień jest synchroniczny i można go odczytać zaraz po wywołaniu funkcji end (). Najbardziej fascynujące jest to, że jest napisane w oficjalnej dokumentacji, ale każdy musi włożyć swoje 5 (wygiętych) centów.
Stroncium

Trollujesz? Być może powinieneś przeczytać dokumentację. Jeśli spróbujesz odczytać strumień przed zdarzeniem końcowym, zakończy się on niepowodzeniem.
Dave

1
Od [ 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. Czytasz go podczas zapisu strona skończyło , nie trzeba nawet czekać do kiedy czytelna strona staje się czytelny (choć na pewno nie). Proszę przeczytać dokumentację.
stroncium

createHmac tworzy strumień . „ zakończony ” w wierszu dokumentacji, który zacytowałeś powyżej, nie oznacza, hmac.end(...)że został wywołany, „ zakończony ” oznacza, że ​​strumień podniósł swoje zakończenie zdarzenia , dlatego polecenie akceptuje wywołanie zwrotne. Po wywołaniu metody end () strumień wymaga czasu, aby opróżnić dane do systemu bazowego. Jeśli wywołasz read () przed zgłoszeniem zdarzenia zakończenia, zakończy się ono niepowodzeniem. Śmiało, wklej kod Gwerdera do JSbin i przekonaj się sam. Powinieneś przeczytać dokumentację dotyczącą strumieni, aby zrozumieć, jak to działa.
Dave

Używam go w kodzie produkcyjnym od jakiegoś czasu i jest stabilny jak diabli. Szczerze mówiąc, nie wiem, co to jest JSBin, ale wypróbowałem również obsługiwany kod w nodejs, używając tylko funkcji kopiuj-wklej i to też działa. Nie należy wyobrażać sobie dodatkowego znaczenia dokumentacji. „zakończony” zawsze oznacza „zakończony” wszędzie w dokumentacji. Znowu wydaje się, że źle rozumiesz, że strumień ma dwie strony. A w dokumentacji wyraźnie stwierdzono, że osoba może korzystać, read()gdy kończy się zapisywalna strona, i nie ma nic o zdarzeniu kończącym.
stroncium
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.