Expand description
OpenID4VCI / OpenID4VP protocol types + reference flows (EUDI Phase 2).
The transport layer that carries Web4 SD-JWT-VCs to and from wallets:
- OID4VCI (issuance): the issuer offers a credential; the wallet pulls it with a holder-key proof. We model the pre-authorized-code grant — the simplest conformant flow, no full OAuth dance.
- OID4VP (presentation): the verifier requests a presentation with a nonce; the wallet returns a VP token (the SD-JWT-VC + holder KB-JWT bound to that nonce + audience).
This module owns the wire message shapes + the verification logic; the HTTP endpoints (in the hub / hestia daemon) are thin wrappers that deserialize a request, call into here, and serialize the result. Everything is testable in-memory without a server.
Generic / public-eligible: standard OpenID4VC shapes, no novel mechanism.
Structs§
- Credential
Issuer Metadata - Issuer metadata — served at
/.well-known/openid-credential-issuer. - Credential
Offer - A Credential Offer (pre-authorized-code grant) — the issuer hands this to the
wallet (QR / link). The
pre_authorized_codeis single-use and binds the subject the issuer will credential. - Credential
Request - The wallet’s Credential Request: an access token (= the redeemed pre-auth
code, in this minimal flow) + a holder-key proof (
jwtproof type) so the issued credential can becnf-bound to the holder. - Presentation
Request - The verifier’s Authorization Request — sent to the wallet. Carries the
noncethe holder KB-JWT must bind to and theresponse_urito POST to. - Presentation
Response - The wallet’s Authorization Response: the VP token (the presented SD-JWT-VC with holder KB-JWT).
Functions§
- build_
holder_ proof - Build a holder key-possession proof JWT (wallet side). Binds to the issuer
(
aud) and ac_noncethe issuer supplied, signed by the holder key. The holder’s public key travels in the JWT header (jwk) so the issuer can both verify the proof andcnf-bind the credential to it. - build_
presentation - Wallet side: build a presentation response for
req, revealing the requested claims, binding the KB-JWT to the verifier’s nonce + client_id. - jwt_
payload_ claim - Read a string claim from a compact JWT’s payload WITHOUT verifying the
signature. Works on a full
header.payload.sigJWT or a bareheader.payloadsigning input (it only reads the payload segment). For pre-verification routing, or for an external signer validating that the bytes it’s about to sign match a claimed intent (e.g. iss / vct / sub). - opaque_
token - SHA-256 hex helper (for opaque single-use codes/nonces in a daemon store).
- proof_
nonce - Peek at the (UNVERIFIED)
noncean OID4VCI holder proof binds to, so an issuer can look up whichc_nonceit minted before callingverify_holder_proof(which takes the expected nonce as input). Not trusted until the proof verifies. - unverified_
issuer - Peek at the (UNVERIFIED) issuer DID of a presented credential. A verifier
learns the issuer from the credential, but needs the issuer’s public key
to verify it — chicken/egg. This reads the issuer JWS payload’s
issclaim so the verifier can resolve that key, then callsverify_presentation_response. The returned DID is NOT trusted until the presentation verifies under the resolved key. - unverified_
nonce - Peek at the (UNVERIFIED)
noncea presentation’s Key-Binding JWT binds to, so a verifier can look up which of its outstandingPresentationRequests this answers. Not trusted until the KB-JWT verifies inverify_presentation_response. - verify_
holder_ proof - Issuer side: verify a holder proof JWT against the expected
c_nonce+aud, returning the holder’s public key (tocnf-bind the credential). - verify_
presentation_ response - Verifier side: validate the wallet’s response. Checks issuer signature,
holder KB-JWT (bound to our nonce + client_id), and that the credential’s
vct+ required claims are present. Returns the verified claims.