Skip to content

Instantly share code, notes, and snippets.

@cmawhorter
Created February 20, 2015 19:40
Show Gist options
  • Select an option

  • Save cmawhorter/690b87b97bc6bf818bd0 to your computer and use it in GitHub Desktop.

Select an option

Save cmawhorter/690b87b97bc6bf818bd0 to your computer and use it in GitHub Desktop.
Deep complex object fingerprinting/hashing in nodejs javascript (recursive).
var crypto = require('crypto');
var ALGO = 'sha256';
function hashValue(val) {
var hash = crypto.createHash(ALGO)
, target;
switch (toString.call(val)) {
case '[object Object]':
target = hashObject(val);
break;
case '[object Array]':
target = hashArray(val);
break;
default:
target = JSON.stringify(val);
break;
}
// console.log('hashValue', val, target);
return hash.update(target).digest('hex');
}
function hashObject(obj) {
var hash = crypto.createHash(ALGO)
, keys = Object.keys(obj || {});
keys.sort(); // order of hash/dict is not guaranteed, so we do alpha
for (var i=0; i < keys.length; i++) {
var key = keys[i]
, val = obj[key]
, signature = hashValue(val);
// console.log('signing - %s: %s => %s', key, val, signature);
hash.update(key);
hash.update(signature);
}
return hash.digest('hex');
}
function hashArray(arr) {
var hash = crypto.createHash(ALGO);
hash.setEncoding('hex');
// FIXME: this probably needs some improvement. i didn't want to just simply
// use arr.length, but if arr order changes the hash won't match
arr.sort();
for (var i=0; i < arr.length; i++) {
var val = arr[i];
hash.update(hashValue(val));
}
return hash.read();
}
module.exports = function(obj) {
return hashValue(obj);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment