46

node.js的crypto模块(至少在撰写本文时)仍未被认为是稳定的,因此 API 可能会发生变化。事实上,互联网上每个人用来获取文件哈希(md5,sha1,...)的方法都被认为是遗留的(来自Hashclass的文档)(注意:强调我的):

类:哈希

用于创建数据哈希摘要的类。

它是一个可读可写的流。写入的数据用于计算哈希。一旦流的可写端结束,使用 read() 方法获取计算的哈希摘要。还支持的 更新和摘要方法。

由 crypto.createHash 返回。

尽管hash.update并被hash.digest认为是遗留的,但引用片段上方显示的示例正在使用它们。

在不使用那些遗留方法的情况下获取哈希的正确方法是什么?

4

6 回答 6

90

从问题中引用的片段中:

【Hash类】是一个可读可写的流。写入的数据用于计算哈希。一旦流的可写端结束,使用 read() 方法获取计算的哈希摘要。

所以你需要散列一些文本是:

var crypto = require('crypto');

// change to 'md5' if you want an MD5 hash
var hash = crypto.createHash('sha1');

// change to 'binary' if you want a binary hash.
hash.setEncoding('hex');

// the text that you want to hash
hash.write('hello world');

// very important! You cannot read from the stream until you have called end()
hash.end();

// and now you get the resulting hash
var sha1sum = hash.read();

如果要获取文件的哈希,最好的方法是从文件中创建一个 ReadStream 并将其通过管道传输到哈希中:

var fs = require('fs');
var crypto = require('crypto');

// the file you want to get the hash    
var fd = fs.createReadStream('/some/file/name.txt');
var hash = crypto.createHash('sha1');
hash.setEncoding('hex');

fd.on('end', function() {
    hash.end();
    console.log(hash.read()); // the desired sha1sum
});

// read all file and pipe it (write it) to the hash object
fd.pipe(hash);
于 2013-09-06T13:06:59.917 回答
36

一个为哈希摘要返回 Promise 的 ES6 版本:

function checksumFile(hashName, path) {
  return new Promise((resolve, reject) => {
    const hash = crypto.createHash(hashName);
    const stream = fs.createReadStream(path);
    stream.on('error', err => reject(err));
    stream.on('data', chunk => hash.update(chunk));
    stream.on('end', () => resolve(hash.digest('hex')));
  });
}
于 2017-06-20T03:44:31.173 回答
20

卡洛斯回答的简短版本:

var fs = require('fs')
var crypto = require('crypto')

fs.createReadStream('/some/file/name.txt').
  pipe(crypto.createHash('sha1').setEncoding('hex')).
  on('finish', function () {
    console.log(this.read()) //the hash
  })
于 2017-03-14T04:18:57.953 回答
15

进一步润色,ECMAScript 2015

hash.js

'use strict';

function checksumFile(algorithm, path) {
  return new Promise(function (resolve, reject) {
    let fs = require('fs');
    let crypto = require('crypto');

    let hash = crypto.createHash(algorithm).setEncoding('hex');
    fs.createReadStream(path)
      .once('error', reject)
      .pipe(hash)
      .once('finish', function () {
        resolve(hash.read());
      });
  });
}

checksumFile('sha1', process.argv[2]).then(function (hash) {
  console.log('hash:', hash);
});
node hash.js hash.js
hash: 9c92ec7acf75f943aac66ca17427a4f038b059da

至少早在 v10.x 就可以工作:

node --version
v10.24.1
于 2017-12-23T09:23:39.627 回答
6

我成功地使用了 Node 模块 hash,代码变得非常干净和简短。它返回一个承诺,因此您可以将它与 await 一起使用:

const hasha = require('hasha');

const fileHash = await hasha.fromFile(yourFilePath, {algorithm: 'md5'});
于 2020-01-15T14:15:21.293 回答
0
var fs = require('fs');
var crypto = require('crypto');
var fd = fs.createReadStream('data.txt');
var hash = crypto.createHash('md5');
hash.setEncoding('hex');
fd.pipe(hash);
hash.on('data', function (data) {
    console.log('# ',data);
});
于 2018-03-20T16:48:44.947 回答