<!-- Generated from prerendered index.html. HTML SHA-256: 05f90a8345dcd71aeb6525c36f71f515de66e6ba7a6bfbd6ffe3fdb07a1509be -->

# 02 · Activation du portefeuille et émission du PID

> Section autonome du guide [eIDAS 2, échange par échange](https://signature.codethelaw.eu/).

Spécifié, déploiement fin 2026

Protocoles finaux : OpenID4VCI 1.0 (16 septembre 2025), HAIP 1.0 (24 décembre 2025). Cadre juridique : règlements d'exécution (UE) 2024/2977 et 2024/2979, modifiés par (UE) 2026/1731 (en vigueur le 11 août 2026). Portefeuilles certifiés attendus au 24 décembre 2026.

Le portefeuille obtient de l'État des attestations d'identité (PID) liées à des clés qu'il détient dans un composant sécurisé. Chaque échange est conçu pour que l'émetteur sache qu'il parle à une instance de portefeuille certifiée et que les clés auxquelles il lie le PID ne peuvent pas être extraites.

## 2.1 Générer les clés liées aux futurs PID

Portefeuille → WSCD · Génération des clés

### Entrée

Demande du portefeuille au composant sécurisé.

**TEXTE**

```text
Générer N paires de clés ECDSA P-256 (une par exemplaire du lot de PID)
Usage : signature, non exportables, déverrouillage par authentification de l'utilisateur
```

### Traitement

1.  Le WSCD (élément sécurisé ou équivalent certifié) génère les paires de clés en interne.
2.  Les clés privées ne sortent jamais du composant ; seules les clés publiques sont exportées au format JWK.
3.  Le système d'exploitation peut fournir une attestation matérielle de ces clés, que le fournisseur de portefeuille vérifiera.

### Sortie

Clés publiques (JWK).

**JSON**

```json
[
  { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" },
  { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" }
]
```

**Suite :** Ces clés publiques seront attestées par le fournisseur de portefeuille, puis inscrites par l'émetteur dans chaque PID (champ cnf).

## 2.2 Obtenir l'attestation d'instance et l'attestation de clés

Portefeuille → Fournisseur de portefeuille · Attestations

### Entrée

Le portefeuille présente au fournisseur la preuve d'intégrité de l'appareil et les clés publiques.

**TEXTE**

```text
Attestation de la plateforme (intégrité de l'application et de l'appareil)
Clés publiques générées à l'étape 1
```

### Traitement

1.  Le fournisseur vérifie l'intégrité de l'instance et la certification du WSCD.
2.  Il signe une attestation d'instance (Wallet Attestation, OpenID4VCI annexe E) qui servira d'authentification client OAuth.
3.  Il signe une attestation de clés (OpenID4VCI annexe D) listant les clés publiques et leur niveau de protection.
4.  HAIP impose que l'attestation d'instance ne contienne aucun identifiant propre à l'instance : son sub est commun à toutes les instances du même produit.

### Sortie

Deux JWT décodés (exemple).

**JSON**

```json
// Attestation d'instance (authentification client)
{ "typ": "oauth-client-attestation+jwt", "alg": "ES256", "x5c": ["MIIC…"] }
{
  "iss": "https://wallet-provider.example.eu",
  "sub": "eudi-wallet-fr-v1",
  "iat": 1759478400,
  "exp": 1759564800,
  "cnf": { "jwk": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" } }
}

// Attestation de clés
{ "typ": "key-attestation+jwt", "alg": "ES256", "x5c": ["MIIC…"] }
{
  "iss": "https://wallet-provider.example.eu",
  "iat": 1759478400,
  "exp": 1759564800,
  "attested_keys": [ { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" }, … ],
  "key_storage": ["iso_18045_high"],
  "user_authentication": ["iso_18045_high"],
  "certification": "https://…/certificat-du-wscd"
}
```

**NOTE 1.** Divergence connue : la spécification européenne TS3 v1.5 type l'attestation de clés keyattestation+jwt (sans tiret) et retire iss, alors qu'OpenID4VCI 1.0 enregistre key-attestation+jwt. Un émetteur qui compare typ strictement rejettera l'autre forme.

**Suite :** L'attestation d'instance authentifie le portefeuille auprès du serveur d'autorisation (étapes 4 et 6) ; l'attestation de clés accompagne la preuve de possession (étape 8).

## 2.3 Recevoir l'offre d'émission

Fournisseur de PID → Portefeuille · Offre d'attestation

### Entrée

Offre transmise par lien ou QR code (flux à l'initiative de l'émetteur).

**HTTP**

```http
haip-vci://?credential_offer=%7B%22credential_issuer%22%3A…%7D

{
  "credential_issuer": "https://pid.example.fr",
  "credential_configuration_ids": ["pid_dc_sd_jwt", "pid_mso_mdoc"],
  "grants": {
    "authorization_code": { "issuer_state": "eyJhbGciOiJSU0Et…" }
  }
}
```

### Traitement

1.  Le portefeuille récupère les métadonnées de l'émetteur (/.well-known/openid-credential-issuer) et du serveur d'autorisation.
2.  HAIP rend obligatoire la prise en charge du flux authorization\_code par le portefeuille et l'émetteur.
3.  Le règlement 2024/2982 impose de demander le PID dans tous les formats proposés : ici SD-JWT VC et mdoc.

### Sortie

Paramètres retenus.

**TEXTE**

```text
issuer         = https://pid.example.fr
configurations = pid_dc_sd_jwt, pid_mso_mdoc
issuer_state   = eyJhbGciOiJSU0Et…
```

**Suite :** Le portefeuille ouvre une demande d'autorisation poussée (PAR) en se présentant avec son attestation d'instance.

## 2.4 Pousser la demande d'autorisation

Portefeuille → Fournisseur de PID · PAR + PKCE

### Entrée

Requête HTTP (RFC 9126), authentification client par attestation.

**HTTP**

```http
POST /par HTTP/1.1
Host: pid.example.fr
Content-Type: application/x-www-form-urlencoded
OAuth-Client-Attestation: eyJ0eXAiOiJvYXV0aC1jbGllbnQtYXR0ZXN0YXRpb24rand0Ii…
OAuth-Client-Attestation-PoP: eyJ0eXAiOiJvYXV0aC1jbGllbnQtYXR0ZXN0YXRpb24tcG9wK2p3dCI…

response_type=code
&client_id=eudi-wallet-fr-v1
&scope=pid_dc_sd_jwt%20pid_mso_mdoc
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256
&redirect_uri=https%3A%2F%2Fwallet.example.eu%2Fcb
&issuer_state=eyJhbGciOiJSU0Et…
&state=af0ifjsldkj
```

### Traitement

1.  Le serveur vérifie l'attestation d'instance (signature, chaîne x5c jusqu'à la liste des fournisseurs de portefeuille) et sa preuve de possession.
2.  Il conserve le code\_challenge PKCE, condensat d'un secret que seul le portefeuille connaît.
3.  Il enregistre les paramètres et renvoie une référence opaque.

### Sortie

Réponse.

**JSON**

```json
HTTP/1.1 201 Created
{
  "request_uri": "urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c",
  "expires_in": 60
}
```

**Suite :** Le portefeuille redirige l'utilisateur vers /authorize avec cette seule référence : les paramètres ne transitent plus par le navigateur.

## 2.5 Authentifier la personne auprès du fournisseur de PID

Personne → Fournisseur de PID · Authentification nationale

### Entrée

Redirection vers l'autorisation.

**HTTP**

```http
GET /authorize?client_id=eudi-wallet-fr-v1
  &request_uri=urn%3Aietf%3Aparams%3Aoauth%3Arequest_uri%3A6esc_11ACC5bwc014ltc14eY22c
```

### Traitement

1.  Le fournisseur de PID authentifie la personne avec un moyen d'identification électronique de niveau élevé (en France, la CNIe par exemple).
2.  Il affiche ce qui va être émis et recueille le consentement.
3.  Il émet un code d'autorisation à usage unique, lié au code\_challenge.

### Sortie

Retour vers le portefeuille.

**HTTP**

```http
HTTP/1.1 302 Found
Location: https://wallet.example.eu/cb?code=SplxlOBeZQQYbYS6WxSbIA
  &state=af0ifjsldkj
  &iss=https%3A%2F%2Fpid.example.fr
```

**NON PUBLIÉ.** Le moyen d'authentification utilisé par chaque fournisseur de PID relève du schéma national : HAIP le laisse hors de son périmètre.

**Suite :** Le portefeuille vérifie state et iss (RFC 9207), puis échange le code contre un jeton lié à sa clé DPoP.

## 2.6 Obtenir un jeton d'accès lié à une clé

Portefeuille → Fournisseur de PID · Token + DPoP

### Entrée

Requête au point de terminaison token.

**HTTP**

```http
POST /token HTTP/1.1
Host: pid.example.fr
Content-Type: application/x-www-form-urlencoded
OAuth-Client-Attestation: eyJ0eXAiOiJvYXV0aC1jbGllbnQtYXR0ZXN0YXRpb24rand0Ii…
OAuth-Client-Attestation-PoP: eyJ0eXAiOiJvYXV0aC1jbGllbnQtYXR0ZXN0YXRpb24tcG9wK2p3dCI…
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2Iiwiandr…

grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
&redirect_uri=https%3A%2F%2Fwallet.example.eu%2Fcb

// En-tête DPoP décodé
{ "typ": "dpop+jwt", "alg": "ES256", "jwk": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" } }
{ "jti": "-BwC3ESc6acc2lTc", "htm": "POST", "htu": "https://pid.example.fr/token", "iat": 1759478460 }
```

### Traitement

1.  Le serveur vérifie que BASE64URL(SHA-256(code\_verifier)) est égal au code\_challenge reçu en PAR.
2.  Il vérifie la preuve DPoP : signature par la clé jwk, méthode et URL, fraîcheur.
3.  Il émet un jeton d'accès lié à l'empreinte de cette clé : un jeton volé est inutilisable sans elle.

### Sortie

Réponse.

**JSON**

```json
{
  "access_token": "Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU",
  "token_type": "DPoP",
  "expires_in": 300
}
```

**Suite :** Le jeton DPoP autorise l'appel au point de terminaison credential, après récupération d'un nonce frais.

## 2.7 Obtenir un nonce pour la preuve de possession

Portefeuille → Fournisseur de PID · Nonce

### Entrée

Requête.

**HTTP**

```http
POST /nonce HTTP/1.1
Host: pid.example.fr
```

### Traitement

1.  L'émetteur génère une valeur aléatoire à usage unique ; HAIP rend ce point de terminaison obligatoire dès que les attestations sont liées à des clés.

### Sortie

Réponse.

**JSON**

```json
HTTP/1.1 200 OK
Cache-Control: no-store
{ "c_nonce": "wKI4LT17ac15ES9bw8ac4" }
```

**Suite :** Le nonce est signé dans la preuve de possession : une preuve ancienne ne peut pas être rejouée.

## 2.8 Demander le PID avec preuve de possession

Portefeuille → Fournisseur de PID · Requête credential

### Entrée

Requête et preuve décodée.

**HTTP**

```http
POST /credential HTTP/1.1
Host: pid.example.fr
Content-Type: application/json
Authorization: DPoP Kz~8mXK1EalYznwH-LC-1fBAo.4Ljp~zsPE_NeO.gxU
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIs…   (htu = …/credential, ath = SHA-256 du jeton)

{
  "credential_configuration_id": "pid_dc_sd_jwt",
  "proofs": { "jwt": [ "eyJ0eXAiOiJvcGVuaWQ0dmNpLXByb29mK2p3dCIs…" ] }
}

// Preuve décodée : signée dans le WSCD par une clé attestée
{ "typ": "openid4vci-proof+jwt", "alg": "ES256",
  "jwk": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" },
  "key_attestation": "eyJ0eXAiOiJrZXktYXR0ZXN0YXRpb24rand0Ii…" }
{ "aud": "https://pid.example.fr", "iat": 1759478470, "nonce": "wKI4LT17ac15ES9bw8ac4" }
```

### Traitement

1.  L'utilisateur déverrouille la clé dans le WSCD (PIN ou biométrie) pour signer la preuve.
2.  L'émetteur vérifie l'attestation de clés (signature, chaîne x5c, niveau iso\_18045\_high), puis que la clé de la preuve figure dans attested\_keys.
3.  Il vérifie aud, iat et le nonce. Avec une attestation de clés, une seule preuve suffit : l'émetteur devrait émettre un exemplaire par clé attestée, dans la limite de sa taille de lot.

### Sortie

Décision.

**TEXTE**

```text
Clés à lier : attested_keys[0..n-1]
Format       : dc+sd-jwt (puis mso_mdoc par une seconde requête)
```

**Suite :** L'émetteur construit et signe un SD-JWT VC par clé.

## 2.9 Construire le PID au format SD-JWT VC

Fournisseur de PID → Fournisseur de PID · Construction SD-JWT VC

### Entrée

Attributs du PID (règle PID de l'ARF, identifiant de type urn:eudi:pid:1).

**JSON**

```json
family_name   : "DUPONT"
given_name    : "Camille"
birthdate     : "1990-04-12"
nationalities : ["FR"]
+ métadonnées : issuing_authority, issuing_country, date d'expiration, statut
```

### Traitement

1.  Chaque attribut divulgable devient une divulgation : un tableau JSON \[sel, nom, valeur\], encodé en base64url.
2.  Le condensat SHA-256 de chaque divulgation encodée est placé dans le tableau \_sd du JWT. Les valeurs ci-dessous sont réellement calculées.
3.  L'émetteur ajoute la clé publique du portefeuille dans cnf, un pointeur de liste de statut, et signe le JWT en ES256 avec son certificat dans x5c (exigence HAIP).

### Sortie

JWT de l'émetteur et divulgations (valeurs de condensat calculées sur ces divulgations exactes).

**JSON**

```json
// En-tête
{ "alg": "ES256", "typ": "dc+sd-jwt",
  "x5c": ["MIIC…(certificat de signature du fournisseur de PID)", "MIIC…(AC intermédiaire)"] }

// Charge utile
{
  "iss": "https://pid.example.fr",
  "iat": 1759478480,
  "exp": 1767225600,
  "vct": "urn:eudi:pid:1",
  "_sd_alg": "sha-256",
  "_sd": [
    "OxAyE-k0HohdXrCjOFh0lGISjvAvNTGA7RStoHkS5uo",
    "QrHO3rDeFV-UD_NxWKSUa_4VKJoM1naxJH3AUTHELNQ",
    "X8GtBRkhhNtoPq7Rw0EOo3bkv4X042nmtFXTBSxhOcc",
    "7ik4-30XvbGwD_Zc7OaUbI8R4KfwNCa43H_3Q6wPjkQ"
  ],
  "issuing_authority": "FR",
  "issuing_country": "FR",
  "cnf": { "jwk": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" } },
  "status": { "status_list": { "idx": 41207, "uri": "https://pid.example.fr/statuslists/7" } }
}

// Divulgations : [sel, nom, valeur]  =>  base64url  =>  SHA-256 => entrée de _sd
["2GLC42sKQveCfGfryNRN9w", "family_name", "DUPONT"]
  WyIyR0xDNDJzS1F2ZUNmR2ZyeU5STjl3IiwgImZhbWlseV9uYW1lIiwgIkRVUE9OVCJd
["eluV5Og3gSNII8EYnsxA_A", "given_name", "Camille"]
  WyJlbHVWNU9nM2dTTklJOEVZbnN4QV9BIiwgImdpdmVuX25hbWUiLCAiQ2FtaWxsZSJd
["6Ij7tM-a5iVPGboS5tmvVA", "birthdate", "1990-04-12"]
  WyI2SWo3dE0tYTVpVlBHYm9TNXRtdlZBIiwgImJpcnRoZGF0ZSIsICIxOTkwLTA0LTEyIl0
["eI8ZWm9QnKPpNPeNenHdhQ", "nationalities", ["FR"]]
  WyJlSThaV205UW5LUHBOUGVOZW5IZGhRIiwgIm5hdGlvbmFsaXRpZXMiLCBbIkZSIl1d
```

**NOTE 2.** Le même PID est aussi émis en mdoc (ISO/IEC 18013-5) : type de document eu.europa.ec.eudi.pid.1, attributs en CBOR, condensats dans un Mobile Security Object signé en COSE\_Sign1 avec la chaîne x5chain (étiquette 33) et la clé de l'appareil dans deviceKeyInfo. Dans le PID SD-JWT, la date de naissance s'appelle birthdate ; en mdoc, birth\_date.

**Suite :** Le portefeuille stocke le JWT et toutes les divulgations ; il n'en révélera qu'une partie à chaque présentation.

## 2.10 Recevoir le lot de PID

Fournisseur de PID → Portefeuille · Réponse credential

### Entrée

Réponse du point de terminaison credential.

**JSON**

```json
HTTP/1.1 200 OK
Content-Type: application/json
{
  "credentials": [
    { "credential": "eyJhbGciOiJFUzI1NiIsInR5cCI6ImRjK3NkLWp3dCIs…~WyIyR0xD…~WyJlbHVW…~WyI2SWo3…~WyJlSTha…~" },
    { "credential": "eyJhbGciOiJFUzI1NiIsInR5cCI6ImRjK3NkLWp3dCIs…~…~" }
  ],
  "notification_id": "3fwe98js"
}
```

### Traitement

1.  Le portefeuille vérifie la signature de chaque exemplaire et que cnf correspond bien à l'une de ses clés.
2.  Chaque exemplaire porte un sel et un index de statut différents : présentés à des services distincts, ils ne sont pas corrélables par leurs valeurs techniques.
3.  Le portefeuille inscrit l'émission dans son journal de transactions.

### Sortie

État du portefeuille.

**TEXTE**

```text
n exemplaires de PID SD-JWT VC, chacun lié à une clé distincte du WSCD
+ exemplaires mdoc
```

**Suite :** Le portefeuille peut présenter ce PID à un service (section 3) ; chaque exemplaire n'est utilisé qu'une fois pour limiter la corrélation entre services.

## Sources

-   [OpenID for Verifiable Credential Issuance 1.0](https://openid.net/specs/openid-4-verifiable-credential-issuance-1_0.html)
-   [OpenID4VC High Assurance Interoperability Profile 1.0](https://openid.net/specs/openid4vc-high-assurance-interoperability-profile-1_0.html)
-   [RFC 9901, Selective Disclosure for JWTs](https://www.rfc-editor.org/info/rfc9901)
-   [ARF, annexe 3.01, règle PID (urn:eudi:pid:1, eu.europa.ec.eudi.pid.1)](https://eu-digital-identity-wallet.github.io/eudi-doc-architecture-and-reference-framework/2.4.0/annexes/annex-3/annex-3.01-pid-rulebook/)
-   [Règlement d'exécution (UE) 2024/2977 (PID et attestations)](https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=OJ:L_202402977)
-   [Règlement d'exécution (UE) 2024/2982 (protocoles et interfaces)](https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=OJ%3AL_202402982)
-   [Règlement d'exécution (UE) 2026/1731 du 15 juillet 2026 (JO du 22 juillet ; mise à jour des normes du portefeuille)](https://eur-lex.europa.eu/eli/reg_impl/2026/1731/oj/fra)
-   [iGrant.io, comparaison OpenID4VCI 1.0 et TS3 v1.5](https://eudi-wallet-wua-playground.igrant.io/openid4vci-vs-ts03)
