Làm cách nào để tôi sử dụng Node.js Crypto để tạo băm HMAC-SHA1?


Câu trả lời:


366

Tài liệu về tiền điện tử: 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' không phải lúc nào cũng cần thiết, ví dụ để thực hiện việc tiêu hóa hmac tương đương với ruby.
htafoya

6
Và để xác minh hàm băm, bạn nên sử dụng crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b)): stackoverflow.com/questions/31095905/ trên
baptx


98

Một vài năm trước đây đã nói rằng update()digest()là phương pháp kế thừa và phương pháp API phát trực tuyến mới đã được giới thiệu. Bây giờ các tài liệu nói rằng một trong hai phương pháp có thể được sử dụng. Ví dụ:

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

Đã thử nghiệm trên nút v6.2.2 và v7.7.2

Xem https://nodejs.org/api/crypto.html#crypto_group_hmac . Cung cấp thêm ví dụ cho việc sử dụng phương pháp phát trực tuyến.


Không phải là một lớp lót, và các cuộc gọi không thể bị xiềng xích ... nhưng tôi sẽ sử dụng phương pháp này.
tfmontague

2
Tôi không thể, vì cuộc sống của tôi, làm cho công việc này. hmac.read () trả về "[object SlowBuffer]" và nếu tôi cố đọc nội dung bằng hmac.read (). toString ('hex'); Tôi không nhận được giá trị mong đợi. Nếu tôi sử dụng phương pháp cập nhật / digest deprecated, nó sẽ trả về chuỗi dự kiến. Tôi đang sử dụng điều này để xác thực chữ ký từ POST của bên thứ ba đến máy chủ của tôi. Bất cứ ý tưởng những gì đang xảy ra?
AngraX

Có lẽ hmac.read đang xảy ra trước khi dữ liệu được tuôn ra luồng? Có lẽ hmac.read nên được điều khiển bởi sự kiện kết thúc của luồng?
Dave

Trên thực tế các liên kết mà bạn đăng rõ ràng đề cập đến việc sử dụng updatevà không write. Tôi bối rối, đó là thực hành tốt nhất bây giờ? Tôi không thể tìm thấy các tài nguyên nói điều đó rõ ràng như bạn đề cập đến nó.
SCBuergel.eth

5
Tính đến tháng 11 năm 2016, digestupdateđã không được chấp nhận và được đặc trưng trong các tài liệu hướng dẫn: nodejs.org/api/crypto.html#crypto_class_hmac . Tôi khuyên bạn chỉ nên sử dụng API luồng nếu bạn đang đọc từ một luồng.
Ricardo Tomasi

22

Giải pháp của Gwerder sẽ không hoạt động vì hash = hmac.read();xảy ra trước khi luồng được hoàn thành. Do đó, vấn đề của AngraX. Ngoài ra hmac.writetuyên bố là không cần thiết trong ví dụ này.

Thay vào đó hãy làm điều này:

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

Chính thức hơn, nếu bạn muốn, dòng

hmac.end(text, function () {

có thể được viết

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

bởi vì trong ví dụ này văn bản là một chuỗi utf


Bạn đã sai, không cần thêm một cuộc gọi lại. Luồng này là đồng bộ và có thể đọc được ngay sau khi kết thúc () được gọi. Điều hấp dẫn nhất là nó được viết trong tài liệu chính thức, nhưng mọi người phải đặt 5 xu (uốn cong) của họ vào
stroncium

Bạn đang troll? Có lẽ bạn nên đọc tài liệu. Nếu bạn cố đọc luồng trước sự kiện kết thúc, nó sẽ thất bại.
Dave

1
Từ [ 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. Bạn đọc nó khi ghi bên kết thúc , bạn không cần phải chờ đợi, ngay cả khi có thể đọc được bên trở nên dễ đọc (mặc dù nó chắc chắn không). Đọc tài liệu của bạn xin vui lòng.
stroncium

createdHmac tạo một luồng . "Đã kết thúc " trong dòng tài liệu mà bạn trích dẫn ở trên không có nghĩa là hmac.end(...)đã được gọi, " đã kết thúc " có nghĩa là luồng đã đưa ra sự kiện kết thúc của nó , đó là lý do tại sao lệnh chấp nhận gọi lại. Sau khi phương thức end () được gọi, luồng yêu cầu thời gian để xóa dữ liệu đến hệ thống cơ bản. Nếu bạn gọi read () trước khi sự kiện kết thúc được nêu ra, nó sẽ thất bại. Hãy tiếp tục và viết mã của Gwerder vào JSbin và tự mình xem. Bạn nên đọc tài liệu Streams để hiểu cách thức hoạt động của nó.
Dave

Tôi đã sử dụng nó trong mã sản xuất một thời gian và nó ổn định như địa ngục. Tôi thực sự không biết JSBin là gì, nhưng tôi cũng đã thử mã được hỗ trợ trong nodejs chỉ bằng cách sao chép-dán và nó cũng hoạt động. Bạn không nên tưởng tượng ý nghĩa bổ sung cho tài liệu. "Đã kết thúc" luôn có nghĩa là "kết thúc" ở mọi nơi trong tài liệu. Một lần nữa, bạn dường như hiểu nhầm rằng luồng có 2 mặt. Và trong tài liệu có tuyên bố rõ ràng rằng người đó có thể sử dụng read()khi bên có thể ghi được kết thúc, và không có gì về sự kiện kết thúc.
stroncium
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.