Search code examples
node.jshashcryptographysha256nodejs-stream

Incorrect NodeJS Crypto Hash when using ReadableStream.pipe


I tried calculate the sha256 hash in 2 different ways, only one of which gave the correct result.

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

Output:

e806a291cfc3e61f83b98d344ee57e3e8933cccece4fb45e1481f1f560e70eb1
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

Only f1 gave the correct hash. Is there anyone with the clue to why it is so?


Solution

  • f1 and f2 are process data streams differently. For the f2 you can't use the digest with the pipe. The pipe returns a writable steam I think. Try this:

    function f2(info: NodeJS.ReadableStream) {
      const hasher = createHash('sha256');
      return new Promise((resolve, reject) => {
        info.pipe(hasher)
          .on('finish', () => resolve(hasher.digest('hex')))
          .on('error', (error) => reject(error));
      });
    }