javascriptchecksumcryptojsfileapistreams-api

Calculate file checksum in JS using ReadableStream and PipeTo?


I wish to calculate a file's checksum locally with JS and have been searching for examples of how to accomplish this using the Streams Api and pipeTo, but have only found examples with Node.js which I am not familiar with. What I'm looking for is something like this:

var stream = file.stream();
var hash = CryptoJS.algo.SHA1.create();
await stream.pipeTo(hash);
console.log(hash);

This code does not work since CryptoJS doesn't seem to create WriteableStream. Can I wrap what CryptoJS creates in some kind of shim or sink? Other suggestions?

I could read and append buffers incrementally of course, but the code becomes a bit messy so I was hoping I could leverage pipeTo to avoid complicating the code.


Solution

  • function byteArrayToWordArray(ba) {
        let wa = [], i;
        for (i = 0; i < ba.length; i++) wa[(i / 4) | 0] |= ba[i] << (24 - 8 * i);
        return CryptoJS.lib.WordArray.create(wa, ba.length);
    }
    
    const cryptoJsWritableStream = (hash) => {
      return new WritableStream({
        write(chunk) {
          hash.update(byteArrayToWordArray(chunk));
        },
        close() {},
        abort() {},
      });
    };
    
    const stream = file.stream();
    const hash = CryptoJS.algo.SHA1.create();
    await stream.pipeTo(cryptoJsWritableStream(hash));
    console.log(hash.finalize().toString());