anvilresearch / jose

JSON Object Signing and Encryption for Node.js and the browser
MIT License
24 stars 7 forks source link

Deterministic JSON Stringify #37

Open EternalDeiwos opened 7 years ago

EternalDeiwos commented 7 years ago

A recurring problem that has been seen with regards to hashes and signatures is when properties get switched around between JSON.stringify calls which results in hashes not matching and signatures not verifying successfully despite semantically identical objects.

For example, an object { alg: 'RS256', kid: 'abcd' } could be stringified as:

{"alg":"RS256","kid":"abcd"}

or

{"kid":"abcd","alg":"RS256"}

The result of the stringify operation depends on the original order of the properties in the JSON string (my understanding is that the order is preserved) and the order in which properties are added to the object.

My recommendation is that we replace our stringify calls with our own deterministic stringify function, or one that we import such as json-stable-stringify.

dmitrizagidulin commented 7 years ago

That's a really good idea. (i'd vote for json-stable-stringify)

christiansmith commented 7 years ago

I don't doubt there are cases where this has been a problem, and have often wondered if we'd have to squash bugs caused thusly. In practice, it hasn't bitten me personally.

One reason for this may be the way modinha and json-document schemas are traversed to read/copy data when initializing. That would minimize the sort of property reordering you're talking about. In fact, it may be a deterministic function on it's own.

I could see such schemes causing problems interoperating with JSON data stringified in the "usual" way.

Just for posterity, can you point to a concrete case or two where JSON.stringify() over the same state has resulted in two different values?

EternalDeiwos commented 7 years ago

@christiansmith take a look at:

https://github.com/anvilresearch/jose/blob/master/test/jose/JWDSpec.js#L24-L40

Swap lines 34 and 35 and watch the world burn.