Skip to main content

Wallet and Key Attestations

Overview​

Wallet Unit Attestations allow PID and EAA providers to assess the Wallet Instance and the security of the keys used for credential binding. The Wallet Instance Attestation (WIA) provides assurance about the Wallet Instance itself. The Key Attestation (KA) provides information about the keys and the WSCD or keystore in which they are held.

Terms and Definitions​

  • Wallet Unit Attestation (WUA): an umbrella term for Wallet Instance Attestations (WIAs) and Key Attestations (KAs).
  • Wallet Instance Attestation (WIA): a JWT signed by the Wallet Provider that attests the integrity and authenticity of the Wallet Instance and enables PID Providers and EAA Providers to determine whether the Wallet Instance is trusted and non-revoked. It corresponds to the Client Attestation JWT of OAuth 2.0 Attestation-Based Client Authentication
  • Client Attestation PoP JWT: a request-specific proof generated by the Wallet Instance using the private key corresponding to the WIA's public key in cnf.jwk claim. It demonstrates possession of that key to the Authorization Server. Unlike the WIA, it is not signed by the Wallet Provider.
  • Key Attestation (KA): a JWT signed by the Wallet Provider that attests the security properties of cryptographic keys stored in a WSCD or keystore and enables PID and EAA Providers to determine whether those keys satisfy the requirements for credential binding.

Protocols, Attestation Format and Content​

CIR 2024/2979 modified by CIR 2026/1731 mandates the use of Wallet Instance Attestation (WIAs) and Key Attestation (KAs) during the issuance of PID or device-bound EAA using the OID4VCI protocol. A Key Attestation is only used for device-bound credential issuance. It shall not be sent when issuing non-device-bound EAA. A Wallet Instance Attestation and a Key Attestation are each a JWT as specified in RFC 7519. The Wallet Provider Backend signs the WIA. In the German National EUDI Wallet, the Remote WSCA signs the KA.

The attestations are carried in different parts of the issuance flow. The WIA authenticates the Wallet Instance towards the Authorization Server in Pushed Authorization Requests (PAR) and Token Requests. The KA is conveyed to the Credential Issuer in the proofs field of the Credential Request.

Wallet Instance Attestation Format and Content​

The Wallet Instance Attestation follows the wallet attestation format defined in Appendix E of OID4VCI. The Wallet Instance sends the Client Attestation JWT together with a Client Attestation PoP JWT to the Authorization Server in both the Pushed Authorization Request (PAR) and the Token Request. If the request also carries a client_id parameter, the Authorization Server verifies that it matches the WIA's sub and the PoP's iss.

In addition to the base claims defined in Appendix E of OID4VCI (including the issuer, subject/client_id, validity information, and the WIA's public key in cnf.jwk), CIR 2024/2979 modified by CIR 2026/1731 additionally requires the following information:

  • wallet_name: the identifier of the wallet solution as registered on the list of Wallet Providers (Article 5 of CIR 2024/2980) — not a free-text display name
  • wallet_version: the version of the wallet solution (a claim defined by this CIR 2026/1731, not part of OID4VCI itself)
  • wallet_solution_certification_information: a JSON object with information on the conformity assessment body, certification number, and other certification details
  • client_status: an object with:
    • status referencing the Token Status List entry for the Wallet Instance, and
    • exp specifying until when the Wallet Provider maintains that revocation status.
  • exp: The technical expiry of the WIA. This must not be interpreted as the end of the revocation-status maintenance period.

The WIA should also include wallet_link, a URI with further information about the wallet solution.

Per Appendix E of OID4VCI, the sub claim is the client_id of the Wallet Instance and, for privacy reasons, it is the same value across all Wallet Instances of the same Wallet Provider — it does not identify an individual Wallet Instance. Only cnf.jwk and the client_status status-list index differentiate one Wallet Instance from another.

German National EUDI Wallet: WIA Implementation

The German National EUDI Wallet documentation does not explicitly describe wallet_name, wallet_version and wallet_solution_certification_information in the publicly available WIA chapter. However, they are supported and filled actually with dummy data.

The private key corresponding to the public key in the WIA's cnf.jwk is held in the Wallet's mobile HKS, not in the RWSCD.

Key Attestation Format and Content​

A Key Attestation follows Appendix D of OID4VCI. When required, the Wallet Instance includes it in the Credential Request proofs field, using the jwt or attestation proof type. With the jwt proof type, the Wallet Instance signs the proof with the private key corresponding to the first public key in the KA's attested_keys array. With the attestation proof type, the KA includes a valid issuer-provided nonce.

In addition to the base claims specified in Appendix D of OID4VCI, CIR 2024/2979, as amended by CIR 2026/1731, requires Key Attestations to include the following attributes:

  • key_storage and user_authentication: Arrays describing the attack resistance of the key storage and user-authentication mechanism. Where the KA refers to a WSCD, both must contain iso_18045_high.
  • certification: a URL (a JSON string, per Appendix D.1 of OID4VCI) linking to information on the certification achieved by the WSCD or keystore (e.g. scheme such as Common Criteria, the evaluated Protection Profile, and the evaluation level) — sufficient for a PID/EAA Provider to determine whether the key storage is a WSCD. The certification details themselves are not embedded in the JWT, unlike wallet_solution_certification_information in the Wallet Instance Attestation, which is a JSON object
  • key_storage_status: an object analogue to client_status in the WIA, representing the revocation status of the WSCD/keystore with
    • status referencing the Token Status List entry. The value represents either the revocation status of the WSCD or keystore type used to store the attested keys.
    • exp specifying until when the Wallet Provider maintains that revocation status.
  • attested_keys: at least one attested public key — this is mandatory, not optional, since attesting keys is the purpose of a Key Attestation
  • exp: the technical expiry of the attestation itself (distinct from key_storage_status.exp)
German National EUDI Wallet: KA implementation

The German National EUDI Wallet implementation calls its Key Attestation a Wallet Trust Evidence (WTE). This chapter uses KA to align the implementation terminology with OID4VCI and CIR 2024/2979, as amended by CIR 2026/1731.

The implementation currently supports KAs for keys held in the Remote Wallet Secure Cryptographic Device (RWSCD); local keystore keys are not supported.

KA support is currently limited to PID issuance, and the PID Provider only needs to support the attestation proof type for this wallet.

The Remote WSCA signs the KA. the Wallet Provider Backend (WPB) does not issue or sign the it.

Status Quo in the German National EUDI Wallet

The actual implementation of KA in the German National EUDI Wallet does not support the use of status lists.

The following claims mandated by CIR 2024/2979 modified by CIR 2026/1731, are not supported by the German National EUDI Wallet:

  • key_storage_status
  • certification

Data Minimization​

Attestations should contain the information needed for the relevant trust and security checks without exposing unrelated Wallet Instance capabilities or internal user-account identifiers. In particular, the Wallet Provider should avoid adding identifiers that would enable unnecessary correlation across issuers.

Further information about the Wallet Solution and its certification status should be conveyed via the trust list rather than embedded in the attestation.

Lifecycle​

A Wallet Instance Attestation (WIA) is issued by the Wallet Provider Backend and associated with a Wallet Instance. A Key Attestation (KA) is issued by the party responsible for the key storage and associated with its key(s).

Their reuse is governed by different rules. In particular, reuse of the signed WIA must be distinguished from reuse of the status-list index referenced by its client_status.status claim.

Key Attestation Lifecycle​

A Key Attestation (KA) is used for a single credential issuance or re-issuance process and shall not be reused for another issuance.

KAs are only relevant for device-bound credentials and shall not be provided when issuing non-device-bound EAAs. The technical validity of a KA is independent of the period during which its revocation status is maintained.

German National EUDI Wallet: KA Lifecycle

In the initial PID issuance flow, the KA is also sent to the Token endpoint inside the DPoP proof's key_attestation claim, where it attests the refresh-token key.

The KA is created by the Remote WSCA, using the credential issuer's c_nonce, and is valid for 10 minutes. It is not fetched in advance or stored by the Wallet.

Wallet Instance Attestation Lifecycle and Reuse​

A Wallet Instance Attestation (WIA) shall not be used with more than one Authorization Server. During a single issuance process, the Wallet Instance uses the same WIA in both the Pushed Authorization Request (PAR) and the Token Request.

CIR 2024/2979 modified by CIR 2026/1731 allows the same WIA to be reused across multiple issuance processes with the same Authorization Server, provided the Wallet Provider supports the per-issuer reuse option and the WIA is still valid. Otherwise, a new WIA is required for each issuance process.

Each request must be accompanied by a fresh Client Attestation Proof of Possession (PoP) JWT, signed using the private key corresponding to the public key in the WIA's cnf.jwk claim. Reusing a WIA therefore does not imply reusing its PoP JWT.

Before issuing a WIA, the Wallet Provider must verify the integrity of the Wallet Instance. The WIA is short-lived: its exp value must be less than 24 hours after the integrity verification.

Reuse of the WIA status-list index​

The client_status.status claim references a status-list entry used to determine whether the Wallet Instance has been revoked. This entry has its own lifecycle, independent of the signed WIA. Under CIR 2024/2979 modified by CIR 2026/1731, the Wallet Provider may support per-issuer reuse of the status-list index. In this case:

  • The Wallet Instance keeps track of the status-list index assigned to each Authorization Server and requests the same index when obtaining a new WIA for that server.
  • Before reusing an index, the Wallet Provider verifies that it was previously assigned to the requesting Wallet Instance.
  • The same index must not be used with different Authorization Servers.
  • The Wallet Provider must document this option in its privacy policy, as it allows the provider to determine how many Authorization Servers a Wallet Instance interacts with and how frequently.

If per-issuer reuse is not supported, each newly issued WIA receives a fresh, unlinkable status-list index.

German National EUDI Wallet Configuration

The per-issuer reuse option is currently not supported by the German National EUDI Wallet.

Technical Expiry and Status-maintenance Period​

WIAs and KAs contain two expiry-related values that serve different purposes:

  • exp defines the technical expiry of the attestation itself. According to CIR 2024/2979, as amended by CIR 2026/1731, a WIA must expire less than 24 hours after the Wallet Provider verified the integrity of the Wallet Instance. For KAs, the technical validity period is determined by the Wallet Provider.
  • client_status.exp (WIA) and key_storage_status.exp (KA) define the period until which the Wallet Provider commits to maintain the revocation status at the referenced status-list index.

The technical expiry of an attestation does not affect the Wallet Provider's obligation to maintain its revocation status. For example, a WIA may expire within 24 hours, while its revocation status must remain available for a considerably longer period.

The Wallet Provider must ensure that WIAs and KAs can be presented with a remaining status-maintenance period of at least 31 days at the time they are presented to the Authorization Server or Credential Issuer.

A Credential Issuer may specify a preferred minimum remaining status-maintenance period through its metadata:

  • preferred_client_status_period specifies the preferred remaining status-maintenance period for a WIA.
  • preferred_key_storage_status_period, defined within key_attestations_required, specifies the corresponding period for a KA.

Where these parameters are provided, the Wallet Instance selects an attestation whose remaining status-maintenance period meets the issuer's preference as closely as possible without falling below it. If no suitable attestation is available, the Wallet Instance requests a new one from the Wallet Provider.

Revocation​

CIR 2024/2979 modified by CIR 2026/1731 mandates IETF Token Status Lists as the revocation mechanism for both Wallet Instance Attestations and Key Attestations; see the Status Management chapter for the underlying mechanism.

For Wallet Instance Attestations, revoking a Wallet Instance means revoking the index value(s) in client_status.status across all Wallet Instance Attestations associated with it.

Cryptographic Formats​

Long-Term keys:

  • Wallet Provider has long-term key pair (wp_pub,wp_priv)(wp\_pub, wp\_priv)
  • Wallet Instance generates device key (device_pub,device_priv)(device\_pub, device\_priv)

Artifacts — the Wallet Provider Backend issues two separate, independently signed JWTs:

  • Wallet Instance Attestation: wia:=sign(wallet_data∣device_pub)wp_privwia := \text{sign}(\mathit{wallet\_data} \mid device\_pub)_\text{wp\_priv}
  • Key Attestation: ka:=sign(key_storage_data∣attested_keys)wp_privka := \text{sign}(\mathit{key\_storage\_data} \mid \mathit{attested\_keys})_\text{wp\_priv}

The Client Attestation PoP JWT accompanying a Wallet Instance Attestation is not produced by the Wallet Provider Backend. The Wallet Instance creates it per request and signs it with device_privdevice\_priv, the private key belonging to the device_pubdevice\_pub published in the attestation's cnf.jwk claim:

  • Client Attestation PoP: pop:=sign(iss∣aud∣jti∣iat)device_privpop := \text{sign}(\mathit{iss} \mid \mathit{aud} \mid \mathit{jti} \mid \mathit{iat})_\text{device\_priv}

Sequence Diagrams​

The following non-normative diagram illustrates how a Wallet Instance obtains a Wallet Instance Attestation (WIA) from its Wallet Provider Backend.

Example Issuance of Wallet Instance Attestation​

PlantUML diagram

Samples​

Disclaimer

The samples provided are non-normative and are intended solely to illustrate what the attestations may look like in practice.

Wallet Instance Attestation​

Decoded WIA JWT Header​

{
"typ": "oauth-client-attestation+jwt",
"alg": "ES256",
"x5c": [
"MIIC8DCCAdigAwIBAgIU...WALLET_PROVIDER_CERT...==",
"MIID...INTERMEDIATE_CERT...=="
]
}

Decoded WIA JWT Payload​

{
"iss": "german-national-wallet:wpb:sandbox",
"sub": "https://wallet.example.eu/client",

"wallet_name": "EUDIW-EU-EXAMPLE-001",
"wallet_version": "0.0.1",

"wallet_link": "https://wallet.example.eu/info",

"wallet_solution_certification_information": {
"conformity_assessment_body": {
"name": "Example EU CAB",
"identifier": "CAB-DE-12345"
},
"certification_number": "EU-WALLET-CERT-2026-0042",
"certification_scheme": "EU Digital Identity Wallet Certification",
"certification_date": "2026-06-15",
"certification_status": "valid"
},

"client_status": {
"status": {
"status_list": {
"idx": 98812,
"uri": "https://wallet.example.eu/status-lists/1db75c9b-7080-4e74-abd6-f8c0a4da4559"
}
},
"exp": 1793404800
},

"nbf": 1788190200,
"exp": 1788276600,

"cnf": {
"jwk": {
"kty": "EC",
"crv": "P-256",
"x": "f83OJ3D2xF4m2M7v8...",
"y": "x_FEzRu9z0H8V4..."
}
}
}

wallet_name holds the wallet solution's identifier as registered on the list of wallet providers, not a free-text display name — hence a code such as EUDIW-EU-EXAMPLE-001 rather than a human-readable string. sub is the Wallet Instance's client_id, which — for privacy reasons — is the same across all Wallet Instances of this Wallet Provider; it does not by itself distinguish one Wallet Instance from another.

Client Attestation PoP​

The Wallet Instance generates this second JWT itself for each request and sends it alongside the WIA. It is not signed by the Wallet Provider.

Decoded PoP JWT Header​

{
"typ": "oauth-client-attestation-pop+jwt",
"alg": "ES256"
}

Decoded PoP JWT Payload​

{
"iss": "https://wallet.example.eu/client",
"aud": "https://pid-provider.example.eu",
"jti": "d25d00ab-552b-46fc-ae19-98f440f25064",
"iat": 1788190260,
"challenge":"5c1a9e10-29ff-4c2b-ae73-57c0957c09c4"
}

The header carries no x5c/kid: the verification key is the public key in the WIA's cnf.jwk claim, so the PoP is only verifiable in combination with its WIA. iss repeats the client_id and shall match the WIA's sub. aud is the issuer identifier of the Authorization Server the request goes to. jti is unique per PoP and lets the Authorization Server detect replay. A PoP may also carry a challenge claim where the Authorization Server supplies one.

Key Attestation​

Decoded KA JWT Header​

{
"typ": "key-attestation+jwt",
"alg": "ES256",
"x5c": [
"MIIC8DCCAdigAwIBAgIU...REMOTE_WSCA_CERT...==",
"MIID...INTERMEDIATE_CERT...=="
]
}

Decoded KA JWT Payload​

{
"iss": "https://wallet.example.eu/remote-wsca",
"iat": 1788190200,
"exp": 1788276600,

"certification": "https://cert.example.eu/wscd/CC-2026-1234",

"key_storage": [
"iso_18045_high"
],

"user_authentication": [
"iso_18045_high"
],

"key_storage_status": {
"status": {
"status_list": {
"idx": 271828,
"uri": "https://wallet.example.eu/status/ka/17"
}
},
"exp": 1790874000
},

"attested_keys": [
{
"kty": "EC",
"crv": "P-256",
"alg": "ES256",
"x": "TCAER19Zvu3OHF4j4W4vfSVoHIP1ILilDls7vCeGemc",
"y": "ZxjiWWbZMQGHVWKVQ4hbSIirsVfuecCE6t4jT9F2HZQ"
}
]
}

certification is a plain URL (see OID4VCI Appendix D.1); the resource it points to is expected to convey the certification scheme (e.g. Common Criteria), the evaluated Protection Profile, the evaluation level, and whether the key storage is a WSCD.

Other references​