ietf-wg-jose / json-web-proof

Specification work for JSON Web Proof
https://ietf-wg-jose.github.io/json-web-proof/
Other
98 stars 9 forks source link

Should selective disclosure use 1 or 2 alg types in JPA #12

Closed OR13 closed 10 months ago

OR13 commented 3 years ago

Some proof types have 2 representations, a. "root" or "full disclosure" format... and a "derived" or "selective disclosure format"...

BBS+ is an example.

While it is possible to verify both formats, I wonder if there is some developer / user experience benefit to refusing to verify the "root" type...

This might help discourage sharing every attribute, since no verifier (that cared deeply about user privacy) would accept the root format... this would cause the holder to explicitly derive a subset (potentially not strict) of attributes every time they wanted to present a proof.

Perhaps such privacy considerations are not appropriate for this layer of debate, but certainly clever registration of algorithms might help user privacy here....

For example:

BbsBlsSignature2020 -> registered but prohibited. BbsBlsSignatureProof2020 -> registered and required.

quartzjer commented 2 years ago

This is an excellent privacy consideration, though I would expect it to be in the presentation exchange layer so that it applies unilaterally to both the format and to any selectively disclosable linkable attributes.

As per relating to JWPs, the draft needs to have language added such that an algorithm's verification method MUST NOT verify a JWP that has only been signed and not derived/proofed. That will at least prevent just disclosing the raw issued JWP without having at least run it through the proof generation.

OR13 commented 2 years ago

This seems ready for a PR, we should label issues with "help wanted" or "ready for PR" and try and get more contributors pushing updates.

OR13 commented 2 years ago

This is blocked by the use of the alg in the header... for example, if the full disclosure header and the selective disclosure header need to be the same... the alg needs to be the same.

quartzjer commented 2 years ago

The alg value has to be the same during issuance and presentation, it is intended to only represent which cryptographic subsystem is used to operate on the given JWP.

There is no indicator in the JWP format itself to signify if it is for issuance or for presentation / selective disclosure. Only the algorithm itself can make that determination based both on the proof value it is given and which operation is being requested.

This enables algorithms to decide how they want to support features like delegation, binding, bearer, etc distinctions.

If a use-case requires a hard distinction between issuance/presentation it is easy to implement as a policy by just having a given payload always be non-disclosed during presentation.

Hopefully I understood your statement in the first place :)

OR13 commented 2 years ago

@quartzjer yes you got it.

originally we had discussed an alg for the original "fully disclosure" proof and one for the derived "selective disclosure proof"...

Then a verifier can switch on the alg and call the right verification code.

That won't be possible if the header has to be the same for both.

The good news is that we also agreed that transmitting the "full disclosure proof" was probably a bad idea from a security perspective.

But I think the issue remains, because the holder may want to verify a credential issued to them, before attempting to derive a selective disclosure proof from it.

If the principle that the header must be the same for both full and selective proofs is critical, then the header cannot signal the difference in verification algorithm.

A natural solution would be to put that signature next to or in the proof, since that part is expected to change, but that deviates from the expectations of a JOSE developer.

We have the same issue for merkle proofs.

when holding a credential, you need to know which verify algorithm to call, which means you need a unique name for it that is in the credential.

quartzjer commented 2 years ago

The hard reality here is that it's simply not possible to actually secure any type of distinction between the issuance context and the presentation context outside of what the algorithm can do internally. The holder has no universal means to make verifiable changes that aren't inherent to the algorithm itself.

Since the header is integrity protected by the signer, any modifications the holder would make outside of that to the JWP serialization are just decorations and formatting.

Every instance of a JWP already has a known context by the application based on the protocol or interaction that it was received as part of. That context is the only one that is relevant for it to choose which verification method to call. Some algorithms such as a bearer-only single use one may not even be able to disambiguate regardless of the context. Whereas, ALL unlinkable algorithms will only verify correctly given the right context.

I don't believe having an unsecured context indicator in the serialization alone adds any value, and is even a potential weakness if it can be used to confuse an application.

OR13 commented 2 years ago

@quartzjer I agree with everything you said, but the problem remains, you will need to call a different verify algorithm and if you don't have way to choose from the header these are your only options:

  1. get the information from outside the header (prefix on the signature for example)
  2. sniff the payload and look for nulls (nulls indicate the need to use the selective disclosure verify algorithm)
  3. try both verify algorithms.

Is there another option?

Which of these options should be recommended?

quartzjer commented 2 years ago

It is the application's responsibility to track the context, if it was received in a signing context, or if it was received in a presentation one.

An algorithm may know the difference inherent to the proof (such as if a presentation nonce was used to build the proof), but it isn't required for them to do so.

Some use-cases may require a security-verifiable distinction and can use selective disclosure as a policy to accomplish that, and some may explicitly not want one such as for delegable bearer credentials.

A JWS without any headers to indicate which key it was signed with is still perfectly valid, it requires the application to make this "trust decision" by context. In the case of JWS you can use a header as part of the trust decision, and in the case of JWP you can use a payload (or lack thereof) as part of the trust decision.

Headers with JWP are protected for communicating equally to the holder and verifier. The only content policy the holder can universally apply to a JWP is selective disclosure.

tplooker commented 2 years ago

In general I understand the direction of treating the protected header in this manner, however I still dont see how implementers will be able to distinguish between the two possible JWP structures associated to a scheme like BBS (namely a BBS Signature and BBS proof). One orthogonal question I have to this issue, is how does JWP accomodate any extra information that may be present in a BBS proof that is not in a BBS signature such as the presentation message?

tplooker commented 2 years ago

To be clear in the context of a scheme like BBS, the presentation message is somewhat akin to a protected header in the sense that it cannot be tampered with, however the party responsible for its integrity is not the signer of the original signature but instead the prover/holder deriving the proof. Does this mean perhaps JWP should consider two types of protected headers?

OR13 commented 2 years ago

an unprotected header might be a useful feature.

If there is no unprotected header, the "proof" or "signature" should disambiguate the algorithms... there should be no guess or content sniffing... putting a prefix on the proof of signature is just an un protected header with extra steps :)

quartzjer commented 2 years ago

This is an excellent thread that has had me really thinking, I'm now thinking along the same lines, that a presented JWP needs an additional header element that is generated by only the holder/prover.

@tplooker in order to protect this header for BBS, if the verifier provides a nonce (such as part of the presentation protocol), if we create a header like {"nonce":"abcd...."} (along with any other presentation headers) and use that as the input to the createProof(), is that what you'd expect?

While BBS has this capability, not all algorithms may be able to protect this header as easily. It can't be optionally protected, and adding both a protected and unprotected header doesn't seem ideal at all.

This also highlights that there's two types of "binding" here: a binding from just the holder to the verifier, and a binding from the issuer to the holder to the verifier.

A "bearer" proof has no binding, any entity that holds it can present it. Useful in some specific use-cases.

The holder-verifier only binding is possible with ZKP-based algorithms, where the issued JWP itself is a secret and each presentation is only bound uniquely to the verifier.

The issuer-holder-verifier binding is one where the verifier can see that the binding used in the presentation was the same as the one used during issuance. This is particularly useful when the issuer has a higher assurance in the holding device posture.

A presentation header can be protected by either type, and I'm not sure if the distinction is important with regard to the header as they both provide integrity and protect from replay.

So, yeah, I like the idea of requiring a verification header from the holder. A "bearer" JWP therefore has no presentation form. The verifiable JWP in compact encoding could take the form of VERIFY_HEADER.ISSUER_HEADER.P1~P2~P3.PROOF.

Feedback encouraged :)

tplooker commented 2 years ago

@tplooker in order to protect this header for BBS, if the verifier provides a nonce (such as part of the presentation protocol), if we create a header like {"nonce":"abcd...."} (along with any other presentation headers) and use that as the input to the createProof(), is that what you'd expect?

I may be miss understanding and some of the confusion may lie in the implementation that exists today, but recently at the BBS signature working group we have elected to generalise a BBS proof so that instead of it taking just a nonce when you are creating or verifying a proof, it takes a presentation message, which in its self could be a data structure that contains a nonce. So I think to answer your question around how a BBS proof would map conceptually to this proposal the VERIFY_HEADER would just be the presentation message?

tplooker commented 2 years ago

Also as feedback on the approach I think in general having a new header is worth exploring more.

selfissued commented 2 years ago

Can someone provide a concise description of what the two different headers would be for and would contain (and would not contain)?

quartzjer commented 2 years ago

So I think to answer your question around how a BBS proof would map conceptually to this proposal the VERIFY_HEADER would just be the presentation message?

Yep, that's exactly what I'm thinking, thanks for the confirmation :+1:

quartzjer commented 2 years ago

Can someone provide a concise description of what the two different headers would be for and would contain (and would not contain)?

The names I'm using for each are just for explanation here, I've not thought much about what to actually call/name them.

The ISSUER_HEADER is protected by the Issuer and contains values set only by the Issuer, including iss, alg, etc. The "normal" stuff.

The VERIFY_HEADER is protected by the Holder and contains values regarding the specific presentation to a Verifier, including at least nonce and possibly other presentation exchange values. The VERIFY_HEADER can only be added by an algorithm that supports generating a unique non-replay-able presentation.

A JWP with no VERIFY_HEADER is only a statement by the Issuer. They may be useful for bearer-only use-cases.

OR13 commented 2 years ago

In VC Data Model terms, we would expect this "VERIFY_HEADER" to cover domain and challenge which map to aud and nonce.

dwaite commented 10 months ago

Closing this out since we haven't touched it in a while. The present draft (-02) uses a two headers on presentation, and we allow the presented form to use a different algorithm identifier.