ฉันจะใช้ Node.js Crypto เพื่อสร้างแฮช HMAC-SHA1 ได้อย่างไร


คำตอบ:


369

เอกสารสำหรับ 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' ไม่จำเป็นเสมอไปเช่นการทำ hmac digestive ที่เทียบเท่ากับ ruby
htafoya

6
และเพื่อตรวจสอบแฮคุณควรใช้crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b)): stackoverflow.com/questions/31095905/ …
baptx

1
วงกลมนี้เสร็จสมบูรณ์แล้ว: nodejs.org/api/crypto.html#crypto_crypto
Ricardo Tomasi

98

ไม่กี่ปีที่ผ่านมามันก็บอกว่าupdate()และdigest()เป็นวิธีการดั้งเดิมและวิธีการสตรีมมิ่งใหม่ API ได้รับการแนะนำ ตอนนี้เอกสารบอกว่าสามารถใช้วิธีใดวิธีหนึ่งได้ ตัวอย่างเช่น:

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

ทดสอบบนโหนด v6.2.2 และ v7.7.2

ดูhttps://nodejs.org/api/crypto.html#crypto_class_hmac ให้ตัวอย่างเพิ่มเติมสำหรับการใช้วิธีการสตรีม


ไม่ใช่สายการบินเดียวและการโทรไม่สามารถถูกผูกมัดด้วยเดซี่ ... แต่ฉันจะใช้วิธีนี้
tfmontague

2
ฉันใช้ชีวิตนี้ไม่ได้สำหรับชีวิตของฉัน hmac.read () ส่งคืน "[object SlowBuffer]" และถ้าฉันพยายามอ่านเนื้อหาโดยใช้ hmac.read (). toString ('hex'); ฉันไม่ได้รับค่าที่คาดหวัง ถ้าฉันใช้วิธีการอัปเดต / แยกตัวเลิกใช้มันจะส่งคืนสตริงที่คาดไว้ ฉันใช้สิ่งนี้เพื่อตรวจสอบลายเซ็นจาก POST ของบุคคลที่สามไปยังเซิร์ฟเวอร์ของฉัน ความคิดใด ๆ ที่เกิดขึ้น?
AngraX

บางที hmac.read กำลังเกิดขึ้นก่อนที่ข้อมูลจะถูกล้างไปยังสตรีมหรือไม่ บางที hmac.read น่าจะได้รับแรงผลักดันจากเหตุการณ์เสร็จสิ้นของกระแส?
เดฟ

อันที่จริงการเชื่อมโยงที่คุณโพสต์ explicitely กล่าวถึงการใช้และไม่ได้update writeฉันสับสนซึ่งเป็นแนวปฏิบัติที่ดีที่สุดในตอนนี้ ฉันไม่สามารถหาทรัพยากรที่บอกได้อย่างชัดเจนว่าคุณพูดถึงมัน
SCBuergel.eth

5
ในฐานะที่เป็นพฤศจิกายน 2016 digestและupdateมีไม่ได้รับการคัดค้านและมีความสำคัญในเอกสาร: nodejs.org/api/crypto.html#crypto_class_hmac ฉันขอแนะนำให้ใช้สตรีม API เฉพาะเมื่อคุณอ่านจากสตรีมเท่านั้น
Ricardo Tomasi

22

วิธีการแก้ปัญหาของ Gwerder จะไม่ทำงานเพราะhash = hmac.read();เกิดขึ้นก่อนที่กระแสข้อมูลจะสิ้นสุด ดังนั้นปัญหาของ AngraX รวมถึงhmac.writeคำสั่งที่ไม่จำเป็นในตัวอย่างนี้

ทำสิ่งนี้แทน:

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

เป็นทางการมากขึ้นถ้าคุณต้องการเส้น

hmac.end(text, function () {

สามารถเขียนได้

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

เพราะในตัวอย่างข้อความนี้เป็นสตริง utf


คุณผิดคุณไม่จำเป็นต้องเพิ่มการโทรกลับ สตรีมนี้ซิงโครนัสและสามารถอ่านได้ทันทีหลังจากสิ้นสุด () ถูกเรียก สิ่งที่น่าสนใจที่สุดคือมันถูกเขียนไว้ในเอกสารอย่างเป็นทางการ แต่ทุกคนต้องใส่ 5 เซนต์ (งอ) ของพวกเขามา
stroncium

คุณกำลังหมุนรอบ? บางทีคุณควรอ่านเอกสาร หากคุณพยายามอ่านกระแสข้อมูลก่อนจบกิจกรรมเหตุการณ์นั้นจะล้มเหลว
เดฟ

1
จาก [ 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.คุณอ่านมันเมื่อเขียนได้ด้านสิ้นสุดวันที่คุณไม่จำเป็นต้องรอให้แม้กระทั่งเมื่ออ่านด้านกลายเป็นที่อ่านได้ ( แต่มันก็ไม่) โปรดอ่านเอกสารของคุณ
ตรอนเซียม

createHmac สร้างกระแส " สิ้นสุด " ในบรรทัดเอกสารที่คุณอ้างถึงข้างต้นไม่ได้หมายความว่าhmac.end(...)ได้รับการเรียกว่า " สิ้นสุดแล้ว " หมายความว่าสตรีมได้เพิ่มเหตุการณ์เสร็จสิ้นซึ่งเป็นสาเหตุที่คำสั่งยอมรับการโทรกลับ หลังจากเรียกใช้เมธอด end () สตรีมจะต้องใช้เวลาในการล้างข้อมูลไปยังระบบที่เกี่ยวข้อง หากคุณโทร read () ก่อนที่เหตุการณ์จะเสร็จสิ้นการยกเหตุการณ์จะล้มเหลว ไปข้างหน้าและวางโค้ดของ Gwerder ลงใน JSbin และดูด้วยตัวคุณเอง คุณควรอ่านเอกสารStreamsเพื่อทำความเข้าใจว่ามันทำงานอย่างไร
เดฟ

ฉันใช้มันในรหัสการผลิตมาระยะหนึ่งแล้วและมันก็เสถียรเหมือนนรก ฉันไม่รู้ว่า JSBin คืออะไร แต่ฉันก็ลองใช้รหัสที่สนับสนุนใน nodejs ด้วยการ copy-paste และมันก็ใช้ได้เหมือนกัน คุณไม่ควรจินตนาการถึงความหมายเพิ่มเติมของเอกสาร "สิ้นสุด" เสมอหมายถึง "สิ้นสุด" ทุกที่ในเอกสาร อีกครั้งคุณดูเหมือนจะเข้าใจผิดว่ากระแสนั้นมีสองด้าน และในเอกสารมีการระบุไว้อย่างชัดเจนว่าบุคคลสามารถใช้read()เมื่อสิ้นสุดการเขียนได้และไม่มีอะไรเกี่ยวกับเหตุการณ์เสร็จสิ้น
ตรอนเซียม
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.