Resource

Generating a variable length hash with node

planted on in: Node JS.

I wanted to generate a unique hash of a given length for screenshot filenames and found Blake Miner's variableHash.js gist which is able to generate a variable-length hash of data.

Blakes version being 11 years old doesn't work with current Node (v19), there exists a newer version in the fork by @timargra which is only 5 years old, but that version causes "DeprecationWarning: Buffer() is deprecated" warnings.

Below is my version with admittedly minor changes required to get this function working under Node v19:

    const crypto = require('node:crypto');

// Initialization Vector
const IV = Buffer.from('068f7bb47896981d6c8b3f9a186591ae', 'hex');

/**
* Generate a variable-length hash of `data`.
*
* Similar to the answer here: http://crypto.stackexchange.com/a/3559/4829
* If you want a b-bit hash of the message m, then use the first b bits of AES-CTR(SHA256(m)).
* Rather than using the suggested algorithm in the stackexchange answer above, I developed
* my own.
*
* I decided to derive AES256 initialization vector and key from the output of SHA256(data).
* Then, the cipher is fed a zero-filled buffer as plaintext, which is encrypted using this key.
* The result should be a pseudorandom number generator seeded with a 256-bit hash of `data`.
*
* In other words, compute SHA256(m) and treat the resulting 256-bit string as a 256-bit AES key.
* Next, use AES in counter mode (with this key) to generate an unending stream of pseudorandom bits.
* Take the first b bits from this stream, and call it your hash.
*
* @author Blake Miner (bminer), timargra, Simon Dann (carbontwelve)
* @see https://gist.github.com/timargra/016f247dd83dbc97ea1d8f71dea38c3f
* @see https://gist.github.com/bminer/4600432
* @param {*} data
* @param {number} size
* @param {BufferEncoding} encoding
* @returns {string}
*/

module.exports = (data, size = 5, encoding = 'hex') => {
let output = Buffer.alloc(size);
let hash = crypto.createHash('sha256');

hash.update(data);

let cipher = crypto.createCipheriv('aes256', hash.digest(), IV);
let offset = output.write(cipher.update(output).toString('binary'));
output.write(cipher.final().toString('binary'), offset);
return output.toString(encoding);
}
— Blake Miner | link
Page History

This page was first added to the repository on March 20, 2023 in commit 5b4ff09d and has since been amended once. View the source on GitHub.

  1. refactor(#304): move files into src folder
  2. feat: publish generating a variable length hash with node