OID4VCI Key Attestation in JWT format (OpenID4VCI 1.0 draft 15/ID2,
"Key Attestation in JWT format" §D.1, #keyattestation-jwt).
A key attestation is a statement - issued by a Wallet's key storage component or its Wallet Provider - that a set of cryptographic public keys are held in a specific class of secure storage and (optionally) gated behind a specific class of user authentication. A Wallet MAY attach one to a Credential Request, either:
- in the
key_attestationJOSE header of ajwtproof (alongside a proof of possession of one of the attested keys), or - as the sole element of an
attestationproof type (no proof of possession of any attested key - one attestation can vouch for many).
verify/2 validates the attestation JWT and returns its attested_keys
plus any assurance claims (key_storage, user_authentication,
certification). Trust in the signer (the key storage component / Wallet
Provider) is host-supplied, exactly as Attesto.ClientAssertion and
Attesto.WalletAttestation take trusted keys from the caller. Conn-free
and fail-closed.
JWT shape (typ=key-attestation+jwt)
alg- REQUIRED header; MUST NOT benoneor a MAC algorithm.typ- REQUIRED header; MUST bekey-attestation+jwt.iat- REQUIRED.exp- OPTIONAL per the spec text, but "MUST be present if the attestation is used with thejwtproof type". Since this module cannot see the surrounding proof type, it defaults to requiringexp(fail-closed); passrequire_exp: falsefor a deployment that only ever uses theattestationproof type and intentionally issues attestations with no expiry.attested_keys- REQUIRED, a non-empty array of public JWKs.key_storage,user_authentication- OPTIONAL non-empty arrays of attack-potential-resistance strings (iso_18045_*or an ecosystem-defined value).certification- OPTIONAL, a URL.nonce- OPTIONAL; MUST echo the Issuer'sc_noncewhen one was provided. Checked against:noncewhen supplied.
As of this draft, the key attestation JWT carries no formal iss/aud
claim (unlike the Client/Wallet Attestation JWT) - the spec's own example
includes iss, but the normative claim list does not. verify/2 still
lets a caller require and pin :issuer for deployments that populate and
rely on it by convention. When that option is supplied, an absent iss
fails closed.
Summary
Functions
Returns true iff jwk (a public JWK map) is among attested_keys,
compared by RFC 7638 thumbprint rather than raw map equality so key
members in a different order, or an added alg/use/kid, do not cause
a false negative.
Verify a key attestation JWT.
Types
@type verify_error() ::
:invalid_attestation
| :invalid_typ
| :invalid_alg
| :unsupported_critical_header
| :invalid_signature
| :missing_iat
| :invalid_iat
| :missing_exp
| :expired
| :not_yet_valid
| :missing_attested_keys
| :invalid_attested_keys
| :invalid_issuer
| :invalid_nonce
@type verify_opts() :: [ trusted_jwks: map() | [map()], issuer: String.t(), nonce: String.t(), now: DateTime.t() | non_neg_integer(), require_exp: boolean(), accepted_algs: [Attesto.SigningAlg.alg()], enforce_fapi_alg_policy: boolean() ]
Functions
Returns true iff jwk (a public JWK map) is among attested_keys,
compared by RFC 7638 thumbprint rather than raw map equality so key
members in a different order, or an added alg/use/kid, do not cause
a false negative.
Used to cross-check a credential-request proof's holder key against a
key attestation's attested_keys (see Attesto.CredentialProof's
:key_attestation opt).
@spec verify(String.t(), verify_opts()) :: {:ok, verified()} | {:error, verify_error()}
Verify a key attestation JWT.
Required opts
:trusted_jwks- an RFC 7517 JWK Set, a single public JWK map, or a list of public JWK maps the attestation's signature is checked against. Establishing which key-storage components / Wallet Providers to trust is the host's responsibility.
Optional opts
:issuer- when set, the attestation MUST carry anissclaim equal to it. Omit this option when using the specification's issuer-less form and scope the trusted JWKS to the intended attester instead.:nonce- the expectedc_nonce; when set, the attestation'snonceclaim MUST match it exactly.:now- clock reference (DateTime or unix seconds).:require_exp- whetherexpmust be present. Defaults totrue.:accepted_algs- JWS algorithms accepted. Defaults toAttesto.SigningAlg.fapi_algs/0.:enforce_fapi_alg_policy- additionally enforce the FAPI RSA modulus and Edwards-curve restrictions on the attestation signer's key (parity withAttesto.ClientAssertionandAttesto.WalletAttestation). Defaults totruefor every algorithm allowlist. Only explicitfalserelaxes these gates; an empty list always denies all algorithms.
Returns {:ok, %{attested_keys:, key_storage:, user_authentication:, certification:, claims:}}, where attested_keys is the list of public
JWK maps this attestation vouches for.