Bagaimana cara menggunakan Node.js Crypto untuk membuat hash HMAC-SHA1?

198

Saya ingin membuat hash I love cupcakes(ditandatangani dengan kunci abcdeg)

Bagaimana saya bisa membuat hash itu, menggunakan Node.js Crypto?

pengguna847495
sumber

Jawaban:

366

Dokumentasi untuk 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
sumber
'hex' tidak selalu dibutuhkan, misalnya untuk melakukan hmac digest setara dengan ruby.
htafoya
6
Dan untuk memverifikasi hash, Anda harus menggunakan crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b)): stackoverflow.com/questions/31095905/…
baptx
1
Lingkaran selesai: nodejs.org/api/crypto.html#crypto_crypto
Ricardo Tomasi
98

Beberapa tahun yang lalu dikatakan bahwa update()dan digest()adalah metode warisan dan pendekatan Streaming API baru diperkenalkan. Sekarang dokumen mengatakan bahwa salah satu metode dapat digunakan. Sebagai contoh:

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

Diuji pada simpul v6.2.2 dan v7.7.2

Lihat https://nodejs.org/api/crypto.html#crypto_class_hmac . Memberikan lebih banyak contoh untuk menggunakan pendekatan streaming.

Adam Griffiths
sumber
Bukan satu kalimat, dan panggilan tidak bisa dirantai daisy ... tapi saya akan menggunakan pendekatan ini.
tfmontague
2
Saya tidak bisa, untuk kehidupan saya, membuat ini berhasil. hmac.read () mengembalikan "[objek SlowBuffer]" dan jika saya mencoba membaca konten menggunakan hmac.read (). toString ('hex'); Saya tidak mendapatkan nilai yang diharapkan. Jika saya menggunakan pendekatan usang / usang, ia mengembalikan string yang diharapkan. Saya menggunakan ini untuk memvalidasi tanda tangan dari POST pihak ketiga ke server saya. apa yang sedang terjadi?
AngraX
Mungkin hmac.read terjadi sebelum data dibilas ke aliran? Mungkin hmac.read harus didorong oleh acara selesai streaming?
Dave
Sebenarnya tautan yang Anda poskan secara eksplisit menyebutkan penggunaan updatedan bukan write. Saya bingung, praktik mana yang terbaik sekarang? Saya tidak dapat menemukan sumber daya yang mengatakannya sejelas yang Anda sebutkan.
SCBuergel.eth
5
Pada 2016 November, digestdan updatetelah tidak dipakai lagi dan ditampilkan dalam dokumentasi: nodejs.org/api/crypto.html#crypto_class_hmac . Saya sarankan menggunakan API aliran hanya jika Anda membaca dari aliran.
Ricardo Tomasi
22

Solusi Gwerder tidak akan berfungsi karena hash = hmac.read();terjadi sebelum aliran selesai diselesaikan. Demikianlah masalah AngraX. Juga hmac.writepernyataan adalah un-diperlukan dalam contoh ini.

Alih-alih lakukan ini:

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

Lebih formal, jika Anda mau, garis

hmac.end(text, function () {

dapat ditulis

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

karena dalam contoh ini teks adalah string utf

Dave
sumber
Anda salah, tidak perlu menambahkan panggilan balik. Aliran ini sinkron dan dapat dibaca setelah end () dipanggil. Yang paling menarik adalah ini ditulis dalam dokumentasi resmi, tetapi semua orang harus memasukkan 5 sen (bengkok) mereka.
stroncium
Apakah Anda trolling? Mungkin Anda harus membaca dokumentasinya. Jika Anda mencoba membaca aliran sebelum acara selesai, itu akan gagal.
Dave
1
Dari [ 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. Anda membacanya ketika ditulis sisi berakhir , Anda tidak perlu bahkan menunggu ketika dibaca sisi menjadi dibaca (meskipun itu pasti tidak). Baca dokumentasi Anda.
stroncium
createHmac membuat aliran . " berakhir " pada baris dokumentasi yang Anda kutip di atas tidak berarti hmac.end(...)telah dipanggil, " berakhir " berarti bahwa aliran telah meningkatkan acara selesai , itulah sebabnya perintah menerima panggilan balik. Setelah metode end () dipanggil, aliran membutuhkan waktu untuk menyiram data ke sistem yang mendasarinya. Jika Anda memanggil read () sebelum acara selesai dimunculkan, itu akan gagal. Bagikan kode Gwerder ke JSbin dan lihat sendiri. Anda harus membaca dokumentasi Streams untuk memahami cara kerjanya.
Dave
Saya sudah menggunakannya dalam kode produksi untuk beberapa waktu dan itu stabil sekali. Sejujurnya saya tidak tahu apa itu JSBin, tapi saya juga sudah mencoba kode yang didukung di nodejs hanya dengan copy-paste dan berfungsi juga. Anda tidak boleh membayangkan makna tambahan untuk dokumentasi. "berakhir" selalu berarti "berakhir" di mana-mana dalam dokumentasi. Sekali lagi, Anda tampaknya salah paham bahwa aliran memiliki 2 sisi. Dan dalam dokumentasi secara eksplisit dinyatakan bahwa orang dapat menggunakan read()ketika sisi yang dapat ditulis berakhir, dan tidak ada apa-apa tentang acara selesai.
stroncium