Skip to content

Instantly share code, notes, and snippets.

@shanewholloway
Created October 25, 2016 23:25
Show Gist options
  • Save shanewholloway/c0b5a2118025b531b0da37ab9930bc9d to your computer and use it in GitHub Desktop.
Save shanewholloway/c0b5a2118025b531b0da37ab9930bc9d to your computer and use it in GitHub Desktop.
JSON hashing, canonicalization, digests, SHA, MD5
function json_canonical(obj) {
return JSON.stringify(obj, (key, value) => {
if ('object' !== typeof value)
return value // it is a value of some kind
if (value instanceof Array)
return value // Arrays are (already) ordered
// normalize into new object initializing via sorted keys
let result = {}
for(let k of Object.keys(value).sort())
result[k] = value[k]
return result }) }
function json_hash(obj, hash_algorithm='sha1') {
let src_json = json_canonical(obj)
let hash = crypto.createHash(hash_algorithm)
.update(src_json, 'utf8')
hash.src_json = src_json
return hash }
function json_digest(obj, encoding='hex', hash_algorithm='sha1') {
return json_hash(obj, hash_algorithm).digest(encoding) }
'use strict'
const assert = require('assert')
let {json_digest, json_canonical} = require('./json_hashing')
class MyClass { toJSON() { return {lst: [1,2,3], msg: 'was here'} }}
let myObj = new MyClass()
let ans = [
{b: 'bee', c: myObj, a: {z: 'zzeee', d: 'ddeeee'}},
{b: 'bee', a: {z: 'zzeee', d: 'ddeeee'}, c: myObj},
{a: {z: 'zzeee', d: 'ddeeee'}, c: myObj, b: 'bee'},
{a: {d: 'ddeeee', z: 'zzeee'}, c: myObj, b: 'bee'},
].map(e => json_digest(e))
assert.deepEqual(ans, [
'316944236441fe58d5ad02c5d494ffef284657f8',
'316944236441fe58d5ad02c5d494ffef284657f8',
'316944236441fe58d5ad02c5d494ffef284657f8',
'316944236441fe58d5ad02c5d494ffef284657f8'])
assert.equal(ans.reduce((k,v) => k==v ? k : null),
'316944236441fe58d5ad02c5d494ffef284657f8')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment