You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There is no fully fledged example containing a JARM-encrypted Authorization Response, which would be helpful to validate implementations. Right now we only have this
I agree, this would be helpful. Examples that I used for Annex B can be generated using this https://github.com/awoie/annex-b-examples but those are encrypted only, i.e., don't use JWS before encrypting.
giving encrypted JWT examples may not give any concrete benefit to the readers, unless we provide the private key to decrypt them.
the only useful information that might be picked from an encrypted jwt is the header. Anyway, this alone is not so eloquent.
I agree that a representation of the encrypted response is required, while the encrypted payload may be truncated, for editorial and readability reasons, if the private key to decrypt it is not provided
A specification should give a complete working example, if it's needed to provide a public key, that's fine for me.
We could have an encrypted auth response that matches to a previous example of auth request, thus we would only need to add the private key for the auth request example and link to it
Part of what this issue asked for has since landed — §8.3 now carries a full encrypted response plus
the JWK with its d parameter, so the example is actually decryptable, which addresses @paulbastian's point from 2023. Two gaps remain, and having just implemented §8.3 end to end I would
like to make a case for closing them.
1. No example shows that vp_token changes type between the two response modes
§8.1 defines it as an object:
vp_token: REQUIRED. A JSON-encoded object subject to the following requirements: Each key
MUST be the id of a Credential Query in the DCQL query …
direct_post is application/x-www-form-urlencoded, so the object has to be serialised to a string
to travel. direct_post.jwt has a JSON payload, so it has to be a real object. Same parameter, two
encodings — and an implementation moving from one Response Mode to the other has to notice.
The spec states this rule, but only for requests. §5:
In the context of an authorization request according to [RFC6749], parameters containing objects
are transferred as JSON-serialized strings (using the application/x-www-form-urlencoded format as
usual for request parameters).
There is no equivalent sentence for responses, and neither example shows the difference:
§8.2, the form-encoded response — the value is elided exactly where it would be visible:
So the one place a reader could see that vp_token= carries JSON text while the JWT payload
carries a JSON object is behind an ellipsis. Since vp_token is REQUIRED, every implementation
that supports both Response Modes meets this.
Spelling out the §8.2 example would fix it on its own:
For what it is worth, we hit this class of bug concretely. Our wallet built the encrypted payload
from the same values it used for the form body, and the verifier rejected it on a type mismatch. It
happened to be on a response parameter from an earlier draft rather than on vp_token, since that
part of our stack has not moved to 1.0 yet — but the shape of the mistake is identical, and on vp_token it is unavoidable rather than incidental.
2. There is no HPKE example at all
§8.3.1 defines HPKE and gives the session_info structure in hex — which is excellent, and went
straight into our test suite on both sides — but the only worked JWE example in §8.3 is ECDH-ES.
An HPKE example would pin down the parts that differ and are easy to get wrong:
the compact serialization has an empty JWE Initialization Vector and Authentication Tag, so it
contains two empty segments: <header>.<enc>..<ciphertext>.
the JWE Encrypted Key is the HPKE encapsulated secret, not a wrapped CEK
enc MUST NOT be present in the protected header
draft-ietf-jose-hpke-encrypt publishes machine-readable vectors as examples/jose-vectors.json,
and having those meant our RFC 9180 implementations passed on the first run in both languages with
no crypto debugging. A single OID4VP-level example with the private key, in the same spirit, would
carry the OID4VP-specific part — namely that info is session_info rather than empty.
This matters more now that HAIP 1.1 is heading toward HPKE-only profiles: implementers of those
profiles have no worked example to check themselves against.
Context
Go wallet encrypting, TypeScript verifier decrypting, across HPKE-0, HPKE-1, HPKE-2, HPKE-3, HPKE-4 and HPKE-7, plus ECDH-ES. Happy to contribute an HPKE example with its private key if
that would help.
Activity
awoie commentedon Nov 26, 2023
I agree, this would be helpful. Examples that I used for Annex B can be generated using this https://github.com/awoie/annex-b-examples but those are encrypted only, i.e., don't use JWS before encrypting.
peppelinux commentedon Nov 27, 2023
giving encrypted JWT examples may not give any concrete benefit to the readers, unless we provide the private key to decrypt them.
the only useful information that might be picked from an encrypted jwt is the header. Anyway, this alone is not so eloquent.
I agree that a representation of the encrypted response is required, while the encrypted payload may be truncated, for editorial and readability reasons, if the private key to decrypt it is not provided
paulbastian commentedon Nov 28, 2023
A specification should give a complete working example, if it's needed to provide a public key, that's fine for me.
We could have an encrypted auth response that matches to a previous example of auth request, thus we would only need to add the private key for the auth request example and link to it
Sakurann commentedon Jun 13, 2024
@awoie to create a working example with mdocs.
also putting ephemeral pubkey that can be used to decrypt.
awoie commentedon Jan 10, 2025
I assume we should put any example, e.g., SD-JWT VC, that conforms to this new language: #380, right? I'll wait with this PR until #380 got merged.
awoie commentedon Jan 28, 2026
Unassigning this since not a prio for now.
fujie commentedon Aug 31, 2026
Part of what this issue asked for has since landed — §8.3 now carries a full encrypted response plus
the JWK with its
dparameter, so the example is actually decryptable, which addresses@paulbastian's point from 2023. Two gaps remain, and having just implemented §8.3 end to end I would
like to make a case for closing them.
1. No example shows that
vp_tokenchanges type between the two response modes§8.1 defines it as an object:
direct_postisapplication/x-www-form-urlencoded, so the object has to be serialised to a stringto travel.
direct_post.jwthas a JSON payload, so it has to be a real object. Same parameter, twoencodings — and an implementation moving from one Response Mode to the other has to notice.
The spec states this rule, but only for requests. §5:
There is no equivalent sentence for responses, and neither example shows the difference:
§8.2, the form-encoded response — the value is elided exactly where it would be visible:
§8.3, the encrypted payload — the object form, with no counterpart to compare against:
{ "vp_token": {"example_credential_id": ["eyJhb...YMetA"]} }So the one place a reader could see that
vp_token=carries JSON text while the JWT payloadcarries a JSON object is behind an ellipsis. Since
vp_tokenis REQUIRED, every implementationthat supports both Response Modes meets this.
Spelling out the §8.2 example would fix it on its own:
For what it is worth, we hit this class of bug concretely. Our wallet built the encrypted payload
from the same values it used for the form body, and the verifier rejected it on a type mismatch. It
happened to be on a response parameter from an earlier draft rather than on
vp_token, since thatpart of our stack has not moved to 1.0 yet — but the shape of the mistake is identical, and on
vp_tokenit is unavoidable rather than incidental.2. There is no HPKE example at all
§8.3.1 defines HPKE and gives the
session_infostructure in hex — which is excellent, and wentstraight into our test suite on both sides — but the only worked JWE example in §8.3 is ECDH-ES.
An HPKE example would pin down the parts that differ and are easy to get wrong:
contains two empty segments:
<header>.<enc>..<ciphertext>.encMUST NOT be present in the protected headerdraft-ietf-jose-hpke-encryptpublishes machine-readable vectors asexamples/jose-vectors.json,and having those meant our RFC 9180 implementations passed on the first run in both languages with
no crypto debugging. A single OID4VP-level example with the private key, in the same spirit, would
carry the OID4VP-specific part — namely that
infoissession_inforather than empty.This matters more now that HAIP 1.1 is heading toward
HPKE-only profiles: implementers of those
profiles have no worked example to check themselves against.
Context
Go wallet encrypting, TypeScript verifier decrypting, across
HPKE-0,HPKE-1,HPKE-2,HPKE-3,HPKE-4andHPKE-7, plus ECDH-ES. Happy to contribute an HPKE example with its private key ifthat would help.