stacks-network / jsontokens-js

Library for encoding, decoding, and verifying JSON Web Tokens (JWTs) in node.js
MIT License
45 stars 26 forks source link

Adding support for multiple signatures #31

Open bodymindarts opened 6 years ago

bodymindarts commented 6 years ago

I would like to document the required steps for making this library support multiple signatures as per the JWS standard

Support General JWS JSON Serialization Syntax

the schema is:

     {
      "payload":"<payload contents>",
      "signatures":[
       {"protected":"<integrity-protected header 1 contents>",
        "header":<non-integrity-protected header 1 contents>,
        "signature":"<signature 1 contents>"},
       ...
       {"protected":"<integrity-protected header N contents>",
        "header":<non-integrity-protected header N contents>,
        "signature":"<signature N contents>"}]
     }

Additional code

the current structure of the code is very much relying on the assumption of there being 1 signature. Instead of trying to add code to the existing classes I would add use-case specific classes and potentially if deemed useful extract / generalize the code to work for 1 or N sigs.

this would mean adding the following files:

src/multi-signer.js
src/multi-verifier.js

Payload structure

kantai commented 6 years ago

Good notes @bodymindarts -- but I think we'd want to continue to use the JWT standard rather than JWS. JWTs use three Base64-URL strings concatenated together with .s to convey the header, payload, signature respectively (see https://jwt.io/introduction/) -- so we'd need to convey all the signatures in the signature object -- which we can certainly do, we'd just need to use a different verification scheme (e.g., ES256K-P2SH or ES256K-MULTI).

The signature object, which is now just a single signature, would have to contain all the signatures (we would need some way to encode those, but that's easy enough). The verifier, however, would need to be passed the redeem script (or something of the like).

bodymindarts commented 6 years ago

Good notes @bodymindarts -- but I think we'd want to continue to use the JWT standard rather than JWS. JWTs use three Base64-URL strings concatenated together with .s to convey the header, payload, signature respectively (see https://jwt.io/introduction/) -- so we'd need to convey all the signatures in the signature object -- which we can certainly do, we'd just need to use a different verification scheme (e.g., ES256K-P2SH or ES256K-MULTI).

Yeah I thought JWT was a superset of JWS / JWE but now I see that a JWS is only considered a JWT when serialized in its compact form. In that case the JWS standard for serializing multiple signatures won't help. So instead you are suggesting to encode all signatures into the signature section of the JWT. How would this work? A base 64 encoded JSON array perhaps?

The signature object, which is now just a single signature, would have to contain all the signatures (we would need some way to encode those, but that's easy enough). The verifier, however, would need to be passed the redeem script (or something of the like).

As to the verifier needing the redeem script. If the verification scheme sufficiently identifies the type of signature (1 sig, multi-sig, segwit-multi-sig) then the verifier would be able to reconstruct the redeem script (with the help of bitcoinjs-lib) without it needing to be passed in. Alternatively where do you think the code that constructs the redeem script should live?

kantai commented 6 years ago

The redeem script cannot be constructed from the address alone. In bitcoin, the last part of the scriptSig reveals that redeem script. We could use the same encoding as bitcoin (and encode a scriptSig and a witness for p2shwh), and then the verifier would just be instantiated with a bitcoin scriptPubKey (or address) -- though in this case, the signers would be responsible for providing the redeemScript.

bodymindarts commented 6 years ago

It can be constructed from the public keys (which obviously need to be provided, ie part of the payload)