如何使用Node.js Crypto创建HMAC-SHA1哈希?


Answers:


366

加密文档: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摘要。
htafoya

6
要验证哈希,您应该使用crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b))stackoverflow.com/questions/31095905/…–
baptx


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 2014年

2
为了我的一生,我无法完成这项工作。hmac.read()返回一个“ [object SlowBuffer]”,如果我尝试使用hmac.read()。toString('hex')读取内容,我没有得到期望值。如果我不赞成使用update / digest方法,它将返回预期的字符串。我正在使用它来验证从第三方POST到我的服务器的签名。有什么想法吗?
AngraX

也许hmac.read是在数据刷新到流之前发生的?也许hmac.read应该由流的finish事件驱动?
戴夫2014年

实际上,您发布的链接明确提到了updateand 的用法write。我很困惑,现在哪个是最佳实践?我找不到像您提到的那样清楚地表明这一点的资源。
SCBuergel.eth

5
随着2016年11月的,digest并且update没有被废弃,都设有文档中:nodejs.org/api/crypto.html#crypto_class_hmac。我建议仅在从流中读取时使用流API。
里卡多·托马西

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字符串


您错了,没有必要添加回调。此流是同步的,并且在调用end()之后立即可读。最令人着迷的是它写在官方文档中,但每个人都必须投入5(弯曲)美分
。–锶

你在拖钓吗?也许您应该阅读文档。如果尝试在完成事件之前读取流,它将失败。
戴夫2015年

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创建一个。您在上面引用的文档行中的“ end ”并不表示hmac.end(...)已被调用,“ end ”表示流已引发其finish事件,这就是命令接受回调的原因。调用end()方法后,流需要时间才能将数据刷新到基础系统。如果在引发finish事件之前调用read(),它将失败。继续,将Gwerder的代码粘贴到JSbin中,亲自看看。您应该阅读Streams文档以了解其工作原理。
戴夫

我已经在生产代码中使用了一段时间,它非常稳定。老实说,我不知道JSBin是什么,但是我还尝试了nodejs中支持的代码,只需复制粘贴即可,它也可以工作。您不应该想象文档的其他含义。在文档的所有地方,“结束”始终表示“结束”。再一次,您似乎误解了流有两个方面。并且在文档中明确指出,read()可写面结束时,人可以使用,并且与完成事件无关。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.