jose icon indicating copy to clipboard operation
jose copied to clipboard

Deterministic JSON Stringify

Open EternalDeiwos opened this issue 7 years ago • 3 comments

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.

EternalDeiwos avatar Aug 24 '17 20:08 EternalDeiwos

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

dmitrizagidulin avatar Aug 24 '17 21:08 dmitrizagidulin

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?

christiansmith avatar Aug 25 '17 00:08 christiansmith

@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.

EternalDeiwos avatar Aug 25 '17 11:08 EternalDeiwos