Skip to content

在JavaScript中计算SHA-256哈希值

SHA-256算法是一种广泛使用的哈希函数,产生一个256位的哈希值。它在许多安全应用和协议中使用,包括TLS和SSL、SSH、PGP和比特币。

在JavaScript中使用原生API计算SHA-256哈希值很容易,但是在浏览器和Node.js之间有一些差异。由于浏览器实现是异步的,所以提供的两个示例都会返回一个Promise以保持一致性。

浏览器

在浏览器中,您可以使用SubtleCrypto API为给定的值创建一个哈希。您首先需要创建一个新的TextEncoder并使用它来编码给定的值。然后,将其值传递给SubtleCrypto.digest()以生成给定数据的摘要,从而得到一个Promise

由于Promise解析为ArrayBuffer,您需要使用DataView.prototype.getUint32()来读取数据。然后,您需要使用Number.prototype.toString()将数据转换为其十六进制表示形式。使用Array.prototype.push()将数据添加到数组中。最后,使用Array.prototype.join()hexes数组中的值组合成一个字符串。

const hashValue = val =>
  crypto.subtle
    .digest('SHA-256', new TextEncoder('utf-8').encode(val))
    .then(h => {
      let hexes = [],
        view = new DataView(h);
      for (let i = 0; i < view.byteLength; i += 4)
        hexes.push(('00000000' + view.getUint32(i).toString(16)).slice(-8));
      return hexes.join('');
    });

hashValue(
  JSON.stringify({ a: 'a', b: [1, 2, 3, 4], foo: { c: 'bar' } })
).then(console.log);
// '04aa106279f5977f59f9067fa9712afc4aedc6f5862a8defc34552d8c7206393'

Node.js

在Node.js中,您可以使用crypto模块为给定的值创建一个哈希。您首先需要使用crypto.createHash()创建一个具有适当算法的Hash对象。然后,使用hash.update()val中的数据添加到Hash中,使用hash.digest()计算数据的摘要。

为了与浏览器实现保持一致,并防止在长时间操作上阻塞,我们将返回一个Promise,通过将其包装在setTimeout()中实现。

import { createHash } from 'crypto';

const hashValue = val =>
  new Promise(resolve =>
    setTimeout(
      () => resolve(createHash('sha256').update(val).digest('hex')),
      0
    )
  );

hashValue(JSON.stringify({ a: 'a', b: [1, 2, 3, 4], foo: { c: 'bar' } })).then(
  console.log
);
// '04aa106279f5977f59f9067fa9712afc4aedc6f5862a8defc34552d8c7206393'

注意事项

  • 这两个实现不兼容。不能在Node.js中使用浏览器实现,反之亦然。
  • 对于相同的输入,两个实现应该产生相同的结果。