Skip to content

Missing examples for JARM-encrypted response #68

Open

Description

@paulbastian

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

Activity

  1. awoie commented on Nov 26, 2023

    @awoie
    Contributor

    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.

  2. peppelinux commented on Nov 27, 2023

    @peppelinux
    Member

    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

  3. paulbastian commented on Nov 28, 2023

    @paulbastian
    ContributorAuthor

    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

  4. Sakurann commented on Jun 13, 2024

    @Sakurann
    Collaborator

    @awoie to create a working example with mdocs.
    also putting ephemeral pubkey that can be used to decrypt.

  5. added this to the 1.1 milestone on Dec 5, 2024
  6. awoie commented on Jan 10, 2025

    @awoie
    Contributor

    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.

  7. removed their assignment
    on Jan 28, 2026
  8. awoie commented on Jan 28, 2026

    @awoie
    Contributor

    Unassigning this since not a prio for now.

  9. fujie commented on Aug 31, 2026

    @fujie

    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:

    Content-Type: application/x-www-form-urlencoded
    
      vp_token=...&
      state=eyJhb...6-sVA
    

    §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 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:

    vp_token=%7B%22my_credential%22%3A%5B%22eyJhbGci...QMA%22%5D%7D&state=...
    

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions