SD-JWT-based Verifiable Credentials (SD-JWT VC), draft-ietf-oauth-sd-jwt-vc.
The IETF profile of Attesto.SdJwt used by the EUDI wallet stack (and its
High-Assurance Interoperability Profile, HAIP): an SD-JWT whose Issuer-signed
JWT carries a credential type (vct), an issuer (iss), an optional holder
key binding (cnf), an optional Token Status List reference (status), and
the usual temporal claims, typed vc+sd-jwt or dc+sd-jwt in the JOSE typ
header.
This module adds the VC-specific claim rules on top of the base SD-JWT
mechanism; the selective-disclosure machinery, recursive verification, and Key
Binding JWT handling all come from Attesto.SdJwt.
issue/2โ assemble and sign an SD-JWT VC: setsiss/vct/iat(and optionalexp/nbf/cnf/status/sub), makes the chosen credential claims selectively disclosable, and stamps the JOSEtypfrom the optional:typ(vc+sd-jwtordc+sd-jwt; defaults tovc+sd-jwt).verify/3โ verify the issuer signature (typedvc+sd-jwt), reconstruct the disclosed claims, and enforce the VC claim rules:issandvctREQUIRED and non-empty,exp(if present) not passed,nbf(if present) reached. Holder binding is a separate step - pass the returnedcnfkey toAttesto.SdJwt.verify_key_binding/3with the presentation's nonce/audience.
Conn-free and fail-closed, like the rest of attesto core.
Summary
Functions
Issue an SD-JWT VC.
Verify an SD-JWT VC presentation and reconstruct the disclosed claims.
Types
@type verify_error() :: Attesto.SdJwt.verify_error() | :missing_iss | :missing_vct | :expired | :not_yet_valid
Functions
Issue an SD-JWT VC.
Required options:
:iss- the issuer identifier (its.well-known/jwt-vc-issueror DID).:vct- the verifiable credential type (a collision-resistant string/URI).:pem- the issuer signing key (PEM).
Optional:
:claims- the credential subject claims (a map). Defaults to%{}.:disclosable- which of those claim names to make selectively disclosable. Defaults to all of:claims. Registered claims (iss/vct/cnf/status/iat/exp/nbf/sub) are never made disclosable even if listed here - they always remain visible, so a holder cannot strip holder-binding (cnf) or a status reference.:cnf- the holder key-binding confirmation (RFC 7800), e.g.%{"jwk" => holder_public_jwk}. Included for later Key Binding.:status- a Token Status List reference map, typically built withAttesto.StatusList.reference/2. Always visible when present.:iat/:exp/:nbf/:sub- standard claims (unix seconds / string).:now- clock reference for a defaulted:iat.:kid- JOSEkidheader.:sd_alg- SD hashing algorithm.:typ- the SD-JWT VC media type stamped in the JOSEtypheader,"vc+sd-jwt"or"dc+sd-jwt"(the credential configuration'sformat). Defaults to"vc+sd-jwt".:x5c- the issuer X.509 certificate chain (RFC 7515 ยง4.1.6): a non-empty list of base64 DER certificate strings, stamped in the JOSEx5cheader so a verifier can bind the credential to a trusted issuer certificate (HAIP). Omitted when nil.
Returns the SD-JWT VC Issuance string (no Key Binding JWT).
@spec verify(String.t(), map() | [map()] | list(), keyword()) :: {:ok, verified()} | {:error, verify_error()}
Verify an SD-JWT VC presentation and reconstruct the disclosed claims.
jwks is the issuer's JWK Set. Options are passed through to
Attesto.SdJwt.verify/3 (e.g. :accepted_algs), plus:
:now/:max_age_seconds- clock reference for the temporal checks.
Returns {:ok, %{claims:, vct:, iss:, cnf:, key_binding_jwt:, ...}}. Holder
binding is NOT checked here - if cnf is present and the presentation carries
a Key Binding JWT, pass both to Attesto.SdJwt.verify_key_binding/3 with the
verifier's expected nonce/audience.