Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reliably hash JavaScript objects?

Is there a reliable way to JSON.stringify a JavaScript object that guarantees that the ceated JSON string is the same across all browsers, Node.js and so on, given that the JavaScript object is the same?

I want to hash JavaScript objects like

{   signed_data: object_to_sign,   signature:   md5(JSON.stringify(object_to_sign) + secret_code) } 

and pass them around across web applications (e.g. Python and Node.js) and the user so that the user can authenticate against one service and show the next service "signed data" for that one to check if the data is authentic.

However, I came across the problem that JSON.stringify is not really unique across the implementations:

  • In Node.js / V8, JSON.stringify returns a JSON string without unnecessary whitespace, such as '{"user_id":3}.
  • Python's simplejson.dumps leaves some whitespace, e.g. '{"user_id": 3}'
  • Probably other stringify implementations might deal differently with whitespace, the order of attributes, or whatever.

Is there a reliable cross-platform stringify method? Is there a "nomalised JSON"?

Would you recommend other ways to hash objects like this?

UPDATE:

This is what I use as a workaround:

normalised_json_data = JSON.stringify(object_to_sign) {   signed_data: normalised_json_data,   signature:   md5(normalised_json_data + secret_code) } 

So in this approach, not the object itself, but its JSON representation (which is specific to the sigining platform) is signed. This works well because what I sign now is an unambiguous string and I can easily JSON.parse the data after I have checked the signature hash.

The drawback here is that if I send the whole {signed_data, signature} object as JSON around as well, I have to call JSON.parse twice and it does not look as nice because the inner one gets escaped:

{"signature": "1c3763890298f5711c8b2ea4eb4c8833", "signed_data": "{\"user_id\":5}"} 
like image 860
nh2 Avatar asked Apr 05 '11 23:04

nh2


People also ask

How do you hash an object in JavaScript?

There are two ways to construct a Hash instance: the first is regular JavaScript object instantiation with the new keyword, and the second is using the $H function. Passing a plain JavaScript object or a Hash to any of them would clone it, keeping your original object intact.

Do JavaScript objects use hash?

A JavaScript Object is an example of a Hash Table because data is represented a key/value pairs. A hashing function can be used to map the key to an index by taking an input of any size and returning a hash code identifier of a fixed size.

What is hash code in JavaScript?

A hash function is used to map a given key to a location in the hash table. A hash code is the result of running this hash function over a given key. In V8, the hash code is just a random number, independent of the object value.


1 Answers

You might be interested in npm package object-hash, which seems to have a rather good activity & reliability level.

var hash = require('object-hash');  var testobj1 = {a: 1, b: 2}; var testobj2 = {b: 2, a: 1}; var testobj3 = {b: 2, a: "1"};  console.log(hash(testobj1)); // 214e9967a58b9eb94f4348d001233ab1b8b67a17 console.log(hash(testobj2)); // 214e9967a58b9eb94f4348d001233ab1b8b67a17 console.log(hash(testobj3)); // 4a575d3a96675c37ddcebabd8a1fea40bc19e862 
like image 65
Frosty Z Avatar answered Oct 09 '22 17:10

Frosty Z