Generate md5 hash of JSON and compare in Python and JavaScript

Question:

I have a use case where i have to generate md5 hash of a JSON object and compare the hashes in the server and the browser.

The browser client generates hash and then asks the server for the hash of the same resource[ which happens to be a JSON object], and compares both the hashes to decide what to do next.

For server i am using Python and browser client is in Javascript.

For me the hashes generated in both cases do not match. Here’s my code:

Python:

>>> import hashlib
>>> import json

>>> a = {"candidate" : 5, "data": 1}
>>> a = json.dumps(a, sort_keys = True).encode("utf-8")
>>> hashlib.md5(a).hexdigest()
>>> 12db79ee4a76db2f4fc48624140adc7e

JS:
I am using md5 for hashing in browser

> var hash = require("md5")
> var data = {"candidate":5, "data":1}
> data = JSON.stringify(data)
> md5(data)
> 92e99f0a99ad2a3b5e02f717a2fb83c2

What is it that i am doing wrong?

Asked By: xssChauhan

||

Answers:

You’re assuming that both languages generate JSON that looks identical.

>>> json.dumps({"candidate" : 5, "data": 1}, sort_keys=True)
'{"candidate": 5, "data": 1}'

js> JSON.stringify({"candidate" : 5, "data": 1})
"{"candidate":5,"data":1}"

Fortunately, they can.

>>> a = json.dumps({"candidate" : 5, "data": 1}, sort_keys=True, indent=2)
'{n  "candidate": 5,n  "data": 1n}'

js> var a = JSON.stringify({"candidate" : 5, "data": 1}, null, 2)
"{n  "candidate": 5,n  "data": 1n}"

And now the hashes would be same as well.

Python:

>>> hashlib.md5(a.encode("utf-8")).hexdigest()
>>> d77982d217ec5a9bcbad5be9bee93027

JS:

>>> md5(a)
>>> d77982d217ec5a9bcbad5be9bee93027

The difference is that json.dumps applies some minor pretty-printing by default but JSON.stringify does not, that’s why hashes are not the same.

  Python:

 >>> import json
 >>> json.dumps({"candidate" : 5, "data": 1})
     '{"candidate": 5, "data": 1}'

  Javacript:

 > JSON.stringify({"candidate" : 5, "data": 1})
   '{"candidate":5,"data":1}'

But with some modification, we can generate the same hash. There are two ways for it:-

  1. Modifying javascript JSON string to make it equivalent to a python JSON string.

    Python:

    >>> import json,hashlib
    >>> a = json.dumps({"candidate" : 5, "data": 1}, sort_keys=True)
    >>> hashlib.md5(a.encode("utf-8")).hexdigest()
        '12db79ee4a76db2f4fc48624140adc7e'
    

    Javacript:

    > const Crypto = require("crypto-js")
      undefined
    > const a = JSON.stringify({"candidate" : 5, "data": 1}).replaceAll(":", ": ").replaceAll(",", ", ")
      undefined
    > Crypto.MD5(a).toString(Crypto.enc.Hex)
      '12db79ee4a76db2f4fc48624140adc7e'
    
  2. Modifying python JSON string to make it equivalent to a javascript JSON string.

    Python:

    >>> import json,hashlib
    >>> a = json.dumps({"candidate" : 5, "data": 1}, separators=(',', ':'))
    >>> hashlib.md5(a.encode("utf-8")).hexdigest()
        '92e99f0a99ad2a3b5e02f717a2fb83c2'
    

    Javacript:

    > const Crypto = require("crypto-js")
      undefined
    > const a = JSON.stringify({"candidate" : 5, "data": 1})
      undefined
    > Crypto.MD5(a).toString(Crypto.enc.Hex)
      '92e99f0a99ad2a3b5e02f717a2fb83c2'
    

    Note:- To run javascript code, crypto-js npm pkg should be installed as same location where you started the node shell.

Answered By: Piyush Kumar
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.