openid / openid/OpenID4VP

transaction_data: interop report + offer of a worked KB-JWT example (multi-credential credential_ids binding)

Open
#754 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Shell
Stars
112
Forks
38
Avg merge
12d 19h
Merged PRs (30d)
4

Description

Context. We implemented OpenID4VP 1.0 transaction_data end-to-end for a research prototype (per-action, human-in-the-loop authorization of a delegated action): an SD-JWT VC credential, a payment-style transaction_data entry, presented from the EUDI reference wallet (a commit-pinned research build) to a conformant verifier. It works end-to-end — request accepted, per-action user confirmation, and the verifier returns 200 once transaction_data_hashes is bound into the holder KB-JWT. Sharing two small things back to the WG. (This is a spec-side note to the DCP WG; distinct from the EUDI wallet-app implementation gap we filed separately at eu-digital-identity-wallet/eudi-lib-android-wallet-core#411.)

1. A worked KB-JWT example the spec could carry (non-normative)

The single most useful missing artefact when building this was one concrete, end-to-end example that walks from the transaction_data array value, through the hash, into the holder KB-JWT. A conformant verifier rejected our first attempts until the KB-JWT carried both transaction_data_hashes and transaction_data_hashes_alg: sha-256 (verifier error: 'transaction_data_hashes_alg' must be 'sha-256'). Once bound, the same verifier accepted.

A fully worked example — the hash below is real and recomputable:

Transaction Data object (before encoding):

{"type":"payment","credential_ids":["payment_card"],"transaction_data_hashes_alg":["sha-256"],"payee":"ACME GmbH","amount":"120.00","currency":"EUR"}

Value as it appears in the transaction_data array (base64url, no padding):

eyJ0eXBlIjoicGF5bWVudCIsImNyZWRlbnRpYWxfaWRzIjpbInBheW1lbnRfY2FyZCJdLCJ0cmFuc2FjdGlvbl9kYXRhX2hhc2hlc19hbGciOlsic2hhLTI1NiJdLCJwYXllZSI6IkFDTUUgR21iSCIsImFtb3VudCI6IjEyMC4wMCIsImN1cnJlbmN5IjoiRVVSIn0

Hash entry = base64url( SHA-256( the base64url string above ) ), no padding (cf. eu-digital-identity-wallet/eudi-app-android-wallet-ui#418):

Xzo6puFg3O2W4vzj3HgQKEROrFEEa8lwkQHFAkM5ff8

Holder KB-JWT payload (SD-JWT VC presentation), hash bound in:

{
  "nonce": "<verifier-nonce>",
  "aud": "x509_hash:<verifier-cert-thumbprint>",
  "iat": "<unix-time>",
  "sd_hash": "<hash-of-issued-sd-jwt>",
  "transaction_data_hashes": ["Xzo6puFg3O2W4vzj3HgQKEROrFEEa8lwkQHFAkM5ff8"],
  "transaction_data_hashes_alg": "sha-256"
}

Reviewer self-check (reproduces the hash entry):

printf %s '<the base64url string>' | openssl dgst -sha256 -binary | basenc --base64url | tr -d '='

If a short non-normative worked example like this would be welcome in the Transaction Data section, I'm happy to open a PR — implementers seem to hit the same "which JWT, which claims, what is the hash input" questions we did.

2. One binding detail to confirm — multi-credential credential_ids

For a single presented credential the binding is unambiguous. For a presentation of multiple credentials where different transaction_data entries carry different credential_ids, we read the spec as: each presented credential's KB-JWT should carry hashes for only those transaction_data objects whose credential_ids reference that credential (per-credential filtering), not the full set. Is that the intended behaviour? We could not find a reference implementation exercising the multi-credential case to check against, so we'd like to confirm the reading before contributing test vectors for it.

Offer

We have a working wallet + verifier setup and can contribute (a) the non-normative KB-JWT example above and (b) interop test vectors for both the single- and multi-credential transaction_data cases, if useful.

Thanks — glad to be contributing.

— Anton Sokolov, Tyche Institute (Tallinn); contribution agreements signed with the OpenID Foundation.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read the OpenID4VP Transaction Data section and reproduce the supplied hash with the openssl command. Confirm the intended per-credential filtering for multi-credential credential_ids, then prepare the non-normative KB-JWT example and single- and multi-credential interop test vectors; done means the WG accepts the interpretation and proposed materials.

Written by the indexing model from the issue text.

Assessment

Domain
documentation
Issue type
Documentation
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.