EUDI Wallet Flows

This page shows how the wallet uses the keystore to obtain a credential (OpenID4VCI) and to present it (OpenID4VP), and lists every key, attestation, proof and token involved. Terms are explained in the Glossary.

These flows are the target design; the REST endpoints they use are not implemented yet.

Every keystore call in these flows is a user request: the wallet signs it with the device keys after a vault unlock and encrypts it, and the Wallet Integration Server forwards it unchanged (see PowerAuth Integration). The Wallet Integration Server cannot read the bodies. The calls to the authorization server and the issuer involve neither it nor the keystore.

An issuance makes three keystore calls: WIA key, WIA, and credential keys. The user enters the PIN or uses biometry once per flow; the SDK then unlocks the vault for each of the three calls. The WIA key has its own call because a refresh reuses it.

Curve. The EUDI user keys, the KA and WIA provider keys and diw-gateway’s EUDI keys are EC P-256, as required today by the OpenID4VC High Assurance Interoperability Profile (HAIP) and the EUDI technical specification TS3. EC P-384 will follow once the EUDI ecosystem supports it. The user-signing keys are EC P-384, plus ML-DSA for a hybrid activation.

Timing. The Wallet Integration Server registers the activation as a unit during the activation, before the commit, and revokes the unit when the activation is removed. KAs and WIAs are not created at activation but just in time, because a key attestation must contain the issuer’s c_nonce.

Issuance of a Credential (OpenID4VCI)

Issuance

  1. WIA key (wallet-instance-keys). The keystore creates a WALLET_INSTANCE key and returns its public key and its wrapped key. The public key becomes the WIA’s cnf. The ARF calls this key the client instance key.
  2. WIA (wallet-instance-attestations). The wallet sends the WIA key’s public key, its wrapped key, and the unsigned proof-of-possession (PoP) JWTs for the pushed authorization request (PAR) and the token request. The keystore checks the PoPs, signs them with the WIA key and verifies the signatures. It returns them with a WIA signed by sign-eudi-ecdsa-wia, valid for 10 minutes.
  3. Credential keys (credential-keys). The wallet sends the number of keys (up to 16) and the issuer’s c_nonce. The keystore creates the CREDENTIAL keys and returns them with a key attestation (KA) signed by sign-eudi-ecdsa-ka. For issuers that require the proof type jwt, the wallet also asks for the proof JWT, which the keystore signs.

Refresh. With a refresh token, the wallet asks the keystore for a new WIA and PoP for the same WIA key. For a re-issuance, it also creates a new key batch with a new KA. The issuer accepts the new attested keys for the same grant.

Presentation of a Credential (OpenID4VP)

Presentation

The wallet presents an SD-JWT VC (selective-disclosure JWT verifiable credential) with a key-binding JWT (KB-JWT). To sign the KB-JWT, it sends the keystore only the SHA-256 of the KB-JWT’s signing input and the credential’s wrapped key (key-binding-signatures). The same call signs the device authentication of an ISO/IEC 18013-5 mdoc.

The keystore accepts only a CREDENTIAL key. It never sees the credential, the disclosures or the verifier. The Wallet Integration Server sees only the encrypted envelope, and the verifier is not involved in the keystore call.

Keys, Attestations, Proofs and Tokens

Wrap and unwrap use the wrap key wrap-user-ecdsa-<n> (AES key wrap); seal and open use the bind key bind-user-ecdsa-<n> (AES-GCM). Every created or unwrapped private key is destroyed right after use.

Shared Keys

Item Type Count Lifetime Stored What the HSM does
wrap-user-ecdsa-<n>, bind-user-ecdsa-<n> key 1 pair per generation <n> until no wrapped key of <n> is in use HSM, user token create: wrap, seal; sign: open, unwrap
Provider CA certificate certificate 1 validity of the certificate HSM, eudi token none; see note below

The provider CA issues the WIA and KA signing certificates and is sent in x5c after the leaf. The self-signed root above it is the trust anchor and is never in x5c.

Wallet Instance Attestation (WIA)

Item Type Count Lifetime Stored What the HSM does
sign-eudi-ecdsa-wia and its certificate key 1 validity of its certificate HSM, eudi token signs each WIA
WIA key (cnf, purpose WALLET_INSTANCE) key 1 per grant until the refresh token expires app storage, wrapped create: generate, wrap, seal; each PoP: open, unwrap, sign
WIA attestation 1 per issuance or refresh 10 minutes – signed by sign-eudi-ecdsa-wia
WIA PoP proof 1 per PAR or token request one request – signed by the WIA key

Key Attestation (KA)

Item Type Count Lifetime Stored What the HSM does
sign-eudi-ecdsa-ka and its certificate key 1 validity of its certificate HSM, eudi token signs each KA
Credential key (purpose CREDENTIAL) key 1 per credential, 1–16 per KA as long as its credential app storage, wrapped create: generate, wrap, seal; each presentation: open, unwrap, sign
KA attestation 1 per key batch 10 minutes – signed by sign-eudi-ecdsa-ka
Proof JWT (proof type jwt) proof 1 per credential request one request (c_nonce) – signed by credential key 0 before it is wrapped
KB-JWT or mdoc device authentication proof 1 per presentation one presentation (nonce) – hash signed by the credential key

A wrapped key in app storage is useless without the device keys.

Wallet Only

These items never reach the Secure Keystore.

Item Type Count Lifetime Stored
PowerAuth activation and its device keys activation 1 per device until removed iOS Keychain / Android Keystore (PowerAuth SDK); device keys encrypted in the vault
Credential (SD-JWT VC or mdoc) credential 1 per credential key set by the issuer encrypted app storage (personal data)
Refresh token token 1 per grant set by the issuer iOS Keychain / Android Keystore; bound to the WIA key
Access token token 1 per token request short, set by the issuer memory
DPoP key key 1 or more per grant as long as its access tokens iOS Keychain / Android Keystore (hardware-backed where available)

The device keys sign every keystore request.

Notes

  • The WIA lifetime is configurable and always below 24 hours.
  • A credential key could sign every presentation of its credential, but each credential of a batch should be presented only once, for unlinkability.
  • A refresh needs a new WIA and PoP. A re-issuance also needs a new KA and new keys. Rotation of the refresh token follows the issuer’s policy.
  • Keys in the HSM for the EUDI flows: the two provider keys (one more of each during rotation) and the wrap and bind keys of each accepted generation, for user-ecdsa and, on an HSM with ML-DSA, user-mldsa.
Last updated on Nov 11, 2026 (21:37) Edit on Github Send Feedback

develop

Secure Keystore