Node.js中ReadableStream.pipe计算Crypto Hash结果错误问题
为什么Node.js中用pipe计算SHA256哈希得到错误结果?
我尝试用两种方法计算SHA256哈希值,但只有其中一种方法得到了正确结果。测试代码如下:
import { createHash } from 'node:crypto'; import { Readable } from 'node:stream'; function f1(info: NodeJS.ReadableStream) { return new Promise((resolve, reject) => { const hash = createHash('sha256'); info.on('data', (data) => hash.update(data)); info.on('end', () => resolve(hash.digest('hex'))); info.on('error', (error) => reject(error)); }); } function f2(info: NodeJS.ReadableStream){ const hasher = createHash('sha256'); return info.pipe(hasher).digest('hex'); } export async function test() { const h1 = await f1(Readable.from('Testing')); const h2 = f2(Readable.from('Testing')); console.log(h1); console.log(h2); } test();
运行输出:
e806a291cfc3e61f83b98d344ee57e3e8933cccece4fb45e1481f1f560e70eb1 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
仅方法f1返回了正确的哈希值,请问这是什么原因?
问题原因
f2的问题在于Stream的pipe操作是异步的,你直接调用digest('hex')的时候,可读流的数据还没来得及写入哈希器,此时哈希器处理的是空输入,所以得到的是空字符串的SHA256哈希值(e3b0c442...)。
而f1通过监听data和end事件,确保在所有数据都写入哈希器后才调用digest,所以能得到正确结果。
修正后的f2实现
要让f2正确工作,需要等到流的finish事件触发后再调用digest,可以把它包装成Promise:
function f2(info: NodeJS.ReadableStream) { return new Promise((resolve, reject) => { const hasher = createHash('sha256'); info.pipe(hasher); hasher.on('finish', () => { resolve(hasher.digest('hex')); }); info.on('error', reject); }); }
同时在test函数里需要用await调用f2,确保异步操作完成后再获取结果:
export async function test() { const h1 = await f1(Readable.from('Testing')); const h2 = await f2(Readable.from('Testing')); console.log(h1); console.log(h2); }
修改后,f2就能输出和f1一致的正确哈希值。
内容的提问来源于stack exchange,提问作者Henry M
相关产品推荐
相关产品推荐

