Skip to content

JSON.stringify order is not deterministic, can lead to signature mismatches for same payload #404

Open
@kevinburke

Description

@kevinburke

If you pass an object as the payload to sign, it eventually gets serialized to a string by calling JSON.stringify, here: https://github.com/brianloveswords/node-jws/blob/master/lib/tostring.js#L9

The output order of JSON.stringify is not guaranteed. For example, one implementation may serialize {one: 'two', three: 'four'} as '{"one":"two","three":"four"}' and another may serialize it as '{"three":"four","one":"two"}'. The former would create a different MAC than the latter.

The latest ECMA spec for JSON.stringify says that it should produce the same order as Object.keys, which should produce the same order as for ... in, which uses Object.[[Enumerate]]() to enumerate object keys. [[Enumerate]] is a) deprecated, and b) the specification contains this note:

The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below.

It might be fine if all you are doing is verifying that a generated signature is valid for the provided payload, and the verification operates on a provided string. But it would be confusing if signing the same payload generated different signatures on different Node versions, or if I generate two different JWT's using the same payload and secret key and, say, HMAC-SHA256, and expect the signatures to be equal.

In any event, you may want to provide a large warning saying that the key ordering isn't deterministic, and you may generate different signatures for the same payload and secret key pair.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions