cyberphone / jws-ct

JWS/CT - JWS "Clear Text" Option
Other
10 stars 4 forks source link

Q. Why compact detached rather than JWS JSON Serialisation #1

Open Justin-Maxwell opened 5 years ago

Justin-Maxwell commented 5 years ago

Qn. Since a key objective is to maintain human readability and general JSON-ness, why not leverage the JWS JSON serialized structures for the meta-info?

   …the syntax of a JWS using the flattened JWS JSON
   Serialization is as follows:
     {
      "payload":"<payload contents>",
      "protected":"<integrity-protected header contents>",
      "header":<non-integrity-protected header contents>,
      "signature":"<signature contents>"
     }

(or it's less-flat alternative for multi-sig) https://tools.ietf.org/html/rfc7515#section-7.2

I'm coming at this from wanting to avoid the complexity overhead of JSON-LD Signatures for (as you suggest) persistent signed JSON documents; finding https://tools.ietf.org/html/rfc7797; thinking all that was missing was some canonicalization; digging into JCS and https://gibson042.github.io/canonicaljson-spec/; discovering that all the 7797 implementations are focussed on detached serializations; and that all the payload examples seem to be of simple strings rather than anything with structure ☹️

And now stumbling across your jws-jcs which also uses the Base64 encoded detached (then re-attached) header and signature, I'm left thinking I must be missing something!??

(although, tbh, I'm not much of a fan of 'payload' as a property name, 'contents' or 'document' or 'body' would be more natural perhaps)

—edit—

So, when I wrote the above, I hadn't realized that this repo belonged to the JCS author/proposer, rather than just some random person's experiment! Thanks for JCS - I really don't understand how there isn't yet a standard for signed JSON documents that are, umm, JSON documents!

cyberphone commented 5 years ago

Hi @Justin-Maxwell, I see the combination of JWS compact and JCS as a reasonable starting point because the JWS compact solution is already established in Open Banking where the compact JWS is supplied in a HTTP header.

For my own use of JCS I have taken a different approach where the JWS Protected Header (here slightly modified) is supplied in clear as well:

{
  "property-1": ... ,
         .
  "property-n": ... ,
  "signature": {
    "algorithm": "ES256",
    "publicKey": {
      "kty": "EC",
      "crv": "P-256",
      "x": "MNGpxRCX3nbLR2IsLIVUpNDkbGJs4FaSCPW0odyIXMY",
      "y": "8gsEOvO5Y5HL-s092cmKp1MQXWUmytp4jBEvnw67weM"
    },
    "value": "4m7_MYwvhAL2Yp6PsayHsAbJvG...Xr8STriy_0iy0NvVZMOvvkEc7HXD_3k1w"
  }
}

The value property holds the signature which is calculated (=using JCS ) over all elements except the value property itself. The publicKey object holds a true subset of a JWK.

Anyway, the outcome of all this depends on the fate of JCS which is now in the IETF ISE (Independent Stream Editor) queue. If this succeeds JCS will become an "Informational" RFC which is not the same as "Full standard" but I don't think that is going to be much of a hurdle.

Justin-Maxwell commented 5 years ago

Thanks. That's very helpful. I can see the sense in your structure. I'm still thinking about having an input/source 'body' property and the 'signature' as sibling properties, do you see any downside to that?

(Also whether to have distinct "signature" and "signer" sibling properties — Did you merge those because it made sense to group all the signing metadata under a single property, or is there some other aspect I don't yet appreciate?)

And now that I know it (JWS (w/JCS) as proper JSON) is generally viable: for our use-case, we will need a couple of chained signatures, I'll try to wrap my head around that — but it seems we could either:

(1) include both public keys under both signatures (since we know the public keys of both signers at the outset); or

(2) take a 'hierarchical' / nesting approach, generate the first signed output document, including the first-signature, and the first-signers public-key; then use that whole document as the input or source 'body' document for the second signature.

The latter feels like it could get a bit ugly, but is also more flexible, as it can work when the subsequent signer is not known when the first signature is computed, and it can be extended to 'n' chained signers.

One final query, if you have thoughts or advice… It seems to me that the signature could be calculated over everything including a "value": null or "value": "" placeholder property. (almost a positive statement of "not yet signed" like the __ on a paper document). There may be advantages (schema?) or disadvantages to that approach I'm not seeing.

Anyhow, thanks again. I hope JCS get its informational RFC status. This 'other' approach of trying to ensure the on-the-wire data is perfectly identical (via b64 encoding or whatever) at both ends feels like JSON / semantic antipattern to me.

cyberphone commented 5 years ago

Thanx! Comment in-line

I'm still thinking about having an input/source 'body' property and the 'signature' as sibling properties, do you see any downside to that?

Such a scheme would of course (from a signature/security point of view) work just fine. The motivation behind the proposed scheme is that I wanted a signature to become an option rather than like for JWS completely change the structure of a signed message.

(Also whether to have distinct "signature" and "signer" sibling properties — Did you merge those because it made sense to group all the signing metadata under a single property, or is there some other aspect I don't yet appreciate?)

This is more or less a "remake" of XML enveloped signatures which I had worked with before turning to JSON.

Now, regarding multiple signatures, there are many possible solutions. I have implemented support for independent multiple signatures where each signature may also hold specific meta data but that is distinct from the JWS-JCS scheme: https://github.com/cyberphone/openkeystore/blob/master/testdata/signatures/p256%23es256%2Cp256-2%23es256%40mult-kid.json

Chained signatures is extensively used in https://cyberphone.github.io/doc/saturn but maybe your use case calls for something more customized? Saturn includes signed objects as properties of outer objects which in turn are signed.

The use of value was also derived from XML. The alternative solution would work fine as well. I have honestly not given this much thought...

Totally agree on the b64 anti pattern 😀

cyberphone commented 5 years ago

https://cyberphone.github.io/doc/security/jsf.html

cyberphone commented 4 years ago

@Justin-Maxwell Chained signatures is now a JSF feature: https://cyberphone.github.io/doc/security/jsf.html#p256_es256_r2048_rs256_chai-jwk.json