Live data from Hacker News

How (not) to sign a JSON object (2019)

latacora.com

31–40 of 45 posts

Re: How (not) to sign a JSON object (2019)

#32
post #17

I have a feeling that idea 2 is a recipe for disaster: > Add the tag and the exact string you signed to the object, validate the signature and then validate that the JSON object is the same as the one you got. In cryptographic practice, redundant information usually spells disaster, because inevitably, someone will use the copy that wasn't verified. But let's dig into it. If I understand this correctly, the suggestio…

Yep. I had a dickens of a time making XML-DSIG secure. I don’t know how they didn’t realize that getElementById returns the first element with an id and doesn’t give a shit if there are multiples. If you chose a different parent element you can get different results. I had to roll my own that threw an error on duplicate IDs and rejected the document.

If you only expect one signature I would recommend you wrap the signed content instead of treating it as a sibling. And even if you have multiple, maybe have signatures be siblings but put them all in the same wrapper. This means the recipient has to know signatures exist but honestly tough shit. If you’re adding sigs you’re going to end up expecting them and that’s a fact not an opinion. You don’t want any tools that ignore the signature and make decisions without validating them first. That’s a Confused Deputy attack waiting to happen.

Also in XML you have to canonicalize the document first, so that any formatting changes don’t invalidate the signature. So a couple other parts of what you said are true but there are solutions, even if annoying ones.

Re: How (not) to sign a JSON object (2019)

#33

Earlier quoted context omitted.

This is why, in one of my projects, I first stringified the JSON using built in JSON.stringify(your_json) function, then signed that string and sent the string, its signature, and public key to server. Server verifies the signature using the string and if passes, then uses JSON.parse(your_string) to get the original json.

The problem is the following two lines produce different outputs, despite having content that means the same thing: console.log(JSON.stringify({ x: 5, y: 6 })); console.log(JSON.stringify({ y: 6, x: 5 }));

Usually, this is not a problem for signing.

Re: How (not) to sign a JSON object (2019)

#34
post #3

This is one of the deeply dissatisfying parts of the Matrix spec. They didn't have any constraints forcing them to embed signatures within the json objects, but they elected to invent their own signing scheme and do it anyways, despite being a greenfield. It also includes support for a special "unsigned" portion for extra data that comes along (which is often used for the server to inject the age of an event). I don'…

I got so much shit for building an API that would not answer any queries about the signed documents until the signature had been verified. Trying to speed up processing and routing by making decisions before the authenticity of the data has been verified is a fool’s errand and false economy. You can’t make decisions based on what might be lies, and malicious ones at that. I spent a lot of time making the signature checks faster rather than buckling and making the signatures a joke.

Re: How (not) to sign a JSON object (2019)

#35
post #24

Another problem with signing JSON: you can have two different json objects that mean the same thing, and will do exactly the same thing in your code e.g. {"a": "foo", "b": "bar"} vs {"b": "bar", "a": "foo"}. Also, whitespace. Are there any standards for normalising json, so that two equivalent, but differently written JSON files will have the same signature?

That's canonicalization, and the article does mention it (but unfortunately does not offer much insight other than that it's hard).

Canonicalization is a pain in the ass. Write yourself a boatload of unit tests.

Re: How (not) to sign a JSON object (2019)

#37
post #24

Another problem with signing JSON: you can have two different json objects that mean the same thing, and will do exactly the same thing in your code e.g. {"a": "foo", "b": "bar"} vs {"b": "bar", "a": "foo"}. Also, whitespace. Are there any standards for normalising json, so that two equivalent, but differently written JSON files will have the same signature?

That's canonicalization, and the article does mention it (but unfortunately does not offer much insight other than that it's hard).

The difficulty stems from you have to rewrite the encoding/decoding canonicalization library in every language you want to consume the data with as opposed to simply piggy backing off of default implementations and the language's standard crypto libs.

For example most JSON parsers default to interpreting numbers from JSON as floats or ints. but in the canonical format you would have to force all parsers to interpret them as exact decimal values. then determine how to encode them (is one hundred "100" or "1e2") etc.

Re: How (not) to sign a JSON object (2019)

#38
post #30

What does JSON object signing provide that TLS doesn't? Does this imply that the application doesn't trust the transport/presentation layers?

Caching or other forms or retransmission of the data.

Not all signed content is meant to be confidential. Or two-party confidential. Think about tokens. You have a refresh token that’s private between you and the destination, but you hand out session tokens to your users so they can talk to the destination directly. Or via another server that doesn’t have a cache coherency with the source.

Re: How (not) to sign a JSON object (2019)

#39
I really wish that XMLDSig wasn't such an awful standard that it turned a good third of the security industry against canonicalization in general.

Saying there's "sure there's lots of ways to serialize, but these specific rules get you the same octet and you sign that" is key to sanity in such situations.

For all of ASN.1's many sins, they got that part absolutely right.

Re: How (not) to sign a JSON object (2019)

#40

Another problem with signing JSON: you can have two different json objects that mean the same thing, and will do exactly the same thing in your code e.g. {"a": "foo", "b": "bar"} vs {"b": "bar", "a": "foo"}. Also, whitespace. Are there any standards for normalising json, so that two equivalent, but differently written JSON files will have the same signature?

Honestly it should not really matter, the regex bait-and-switch solution seem like the most practical one, there is some trickery in checking that the magic key does not appear in the string already but they seems far easier
Post reply on HN