sécurité·12 min de lecture

QWAC vs QSealC : qui fait quoi, et pourquoi vous vous trompez de couche

Le QWAC est lu par la couche TLS, une fois, au handshake. Le QSealC est lu par la couche applicative, à chaque requête. Où vit chaque clé privée, ce que STET exige, et comment lire une « erreur de certificat ».

Les deux certificats sortent du même eIDAS TSP, portent le même numéro d'agrément et les mêmes rôles DSP2, et arrivent souvent sur le même bon de commande. La différence n'est pas dans ce qu'ils contiennent. Elle est dans la couche de la pile qui les lit. Le QWAC est lu par la couche TLS, une fois, au handshake. Le QSealC est lu par la couche applicative, à chaque requête, dans un en-tête HTTP.

Un ticket qui dit « erreur de certificat » sans dire à quelle couche n'est pas diagnosticable. Cet article ne redéfinit pas les deux objets — les fiches QWAC, QSealC et mTLS le font. Il place chacun dans la pile, dans l'infrastructure et dans les logs, avec le texte de STET 1.6.3 en regard. Pour le panorama complet de la stack, lisez d'abord Architecture technique d'une API DSP2.

En une image : deux couches, deux certificats

Une requête DSP2 descend la pile. Chaque certificat n'intervient qu'à un étage.

QWACQSealC
Base eIDAScertificat qualifié d'authentification de site web, art. 3(39)certificat qualifié de cachet électronique, art. 3(30)
Couchetransport (TLS)message (HTTP)
Lu parla pile TLS des deux côtés, au handshakele vérificateur de signature de l'ASPSP, à chaque requête
Fréquenceune fois par connexionune fois par requête — et par réponse si l'ASPSP signe
Survit à un proxy qui termine TLSnonoui
Valeur de preuve après coupaucune : rien n'est conservéla signature reste dans la requête, vérifiable plus tard
Clé privée, côté TPPlà où la connexion sortante est ouvertelà où la requête est construite
Symptôme quand ça cassehandshake rompu, aucun code HTTPHTTP 400 (STET §3.5)
Ce que STET en dit§3.1, §3.2, §3.9§3.5

La RTS (UE) 2018/389, art. 34, autorise l'un ou l'autre pour l'identification. Les standards d'API ont tranché en les empilant : STET et Berlin Group exigent le QWAC pour le canal et le QSealC pour la signature. Deux certificats, donc deux clés privées, deux dates d'expiration et deux procédures de rotation.

Ce que STET exige, texte à l'appui

Trois passages du Framework 1.6.3 (Part 1) suffisent. Les pages sont celles du PDF officiel, que le manuel affiche en marge de chaque paragraphe.

§3.1 et §3.2 — le QWAC, pour TLS et rien d'autre

« Each actor must be provided with at least one eIDAS certificate (QWAC), for TLS 1.2 purpose » (§3.1, p. 17). Le TPP vérifie le QWAC serveur de l'ASPSP et présente le sien ; les deux respectent ETSI TS 119 495 ; « in case of authentication failure, on one side or the other, the connection must be closed » ; et « no additional encrypting or authenticating feature is required » (§3.2, p. 17–18). Le QWAC ne remonte jamais dans la requête : tout ce qu'il a à dire, il le dit au handshake.

Le même paragraphe fixe le format de l'organizationIdentifier du sujet du certificat : PSD, le code pays de la NCA, un tiret, l'identifiant de la NCA, un tiret, le numéro d'agrément — PSDFR-ACPR-12345 pour un acteur agréé par l'ACPR. C'est ce champ, avec les rôles du QC statement ETSI, que l'ASPSP lit dans le certificat client pour savoir qui appelle, et en quelle qualité.

§3.5 — le QSealC, pour signer chaque requête

« Each request sent by the TPP has to be signed and ASPSP might also sign their responses. If the ASPSP notes that the signature is either absent or invalid for a given request, it shall reject this request with HTTP400 » (§3.5, p. 53).

Le mécanisme historique est HTTP Signature dans sa version draft-cavage : un Digest SHA-256 du corps, puis une signature RSA-SHA256 faite avec le QSealC sur (request-target), Date, Content-Type, Content-Length, X-Request-Id, les en-têtes PSU-* et le Digest lui-même, transportée dans l'en-tête Signature avec keyId, algorithm et la liste des en-têtes signés (§3.5.1.1, p. 53–55). Le keyId est soit l'identifiant attribué lors de l'enregistrement OAuth2, soit l'URL du QSealC suffixée d'un _ et de son empreinte SHA-256 (§3.5.1.2, p. 55).

Depuis la 1.6.3, le Framework conseille de remplacer ce mécanisme par le profil JSON Web Signature d'Open Banking Europe : un JWS détaché (RFC 7515) dans l'en-tête x-jws-signature, dont l'en-tête protégé porte x5t#S256, l'empreinte du QSealC signataire, et sigD la liste des en-têtes couverts (§3.5.2, p. 55–56). Le draft-cavage, lui, a été remplacé côté IETF par la RFC 9421 — que STET ne cite pas comme cible.

§3.9 — le QWAC revient une troisième fois, dans OAuth2

« Based on MTLS, the identity of the TPP is provided by its eIDAS certificate during OAuth2 procedures », avec renvoi à la RFC 8705 (§3.9, p. 59). Le serveur d'autorisation authentifie donc le client par tls_client_auth — le QWAC présenté au handshake du POST /token — et peut lier le token émis à ce certificat, par sa claim cnf et l'empreinte x5t#S256. Un token lié à une empreinte qui n'est plus celle présentée est refusé, même s'il n'a pas expiré.

Une requête, trois vérifications

Trois vérifications, trois couches, trois symptômes qui ne se ressemblent pas. L'ordre des deux vérifications applicatives est propre à chaque banque ; le symptôme, lui, ne change pas.

Où vivent les clés privées : l'erreur de couche

C'est ici qu'on se trompe. Les deux clés privées ne vivent pas au même endroit, parce que les deux certificats ne sont pas lus par le même composant.

Côté TPP, en sortie

La clé du QSealC appartient au composant qui construit la requête, parce que la signature couvre des en-têtes — Date, Content-Length, X-Request-Id — qui doivent être figés avant l'envoi. La clé du QWAC appartient au composant qui ouvre la connexion. Si un proxy sortant, un NAT applicatif ou un service mesh ouvre les connexions à la place de l'application, c'est lui qui présente le QWAC, et l'application n'a pas à en tenir la clé. Mettre la clé du QWAC dans l'application alors que le mesh termine et rouvre TLS donne un handshake sans certificat client : une alerte TLS, et aucun code HTTP.

Côté ASPSP, en entrée

Côté banque, le QWAC client s'arrête au composant qui termine TLS. Ce qui passe ensuite est une identité extraiteorganizationIdentifier, rôles, empreinte — transmise dans un en-tête interne que le reste de la chaîne doit pouvoir croire, d'où l'intérêt de le signer ou de ne l'accepter que du terminateur. La signature QSealC, elle, traverse tout : un composant situé n'importe où derrière peut la vérifier, à condition de voir les octets d'origine. Une gateway qui re-sérialise le JSON, recalcule Content-Length ou normalise Date avant le vérificateur produit des 400 sur des requêtes valides.

Les six confusions de couche

#ConfusionCe qui se passeSymptôme
1Clé du QWAC sur un composant qui n'ouvre pas la connexionhandshake sans certificat clientalerte TLS, pas de HTTP
2QSealC présenté comme certificat client TLS, ou QWAC utilisé pour signerle QcType ETSI n'est pas le bon (web pour l'un, eseal pour l'autre) ; un vérificateur qui le contrôle refusealerte TLS, ou 400
3Signature calculée avant un proxy qui réécrit Date, Content-Length ou le corpsla signature porte sur d'autres octets que ceux reçus400, signature invalide
4Vérification faite après une transformation de la requête, côté ASPSPmême cause, en miroir400 sur des requêtes valides
5QWAC renouvelé sans réémettre les tokens liéscnf.x5t#S256 ne correspond plus au certificat présenté401 sur un token non expiré
6AC du QTSP de la banque absente du magasin de confiance du TPPle TPP refuse le QWAC serveur de l'ASPSPunknown_ca, connexion fermée par le TPP lui-même

La confusion 2 est la plus coûteuse, parce qu'elle est invisible tant que la banque ne contrôle pas le type de certificat — et visible d'un coup le jour où elle le fait. Les deux certificats sont souvent vendus ensemble ; ils ne sont pas interchangeables.

Matrice de diagnostic

SymptômeCoucheCertificat en causeOù regarder
Connexion fermée pendant le handshake, aucun code HTTP ; handshake_failure, bad_certificate, certificate_expired, unknown_caTLSQWAC — le vôtre, ou celui de la banque que vous ne reconnaissez paslogs du terminateur TLS ; openssl s_client -cert -key
401tokenQWAC, via le binding RFC 8705 ; ou simplement un token expiréréponse du serveur d'autorisation ; cnf du token contre l'empreinte du certificat présenté
400 mentionnant la signature (STET §3.5)message HTTPQSealCDigest recalculé ; liste des en-têtes signés ; keyId résoluble ; octets réellement envoyés
403, ou code métier de la banqueautorisationaucun des deuxrôles PSD2 du certificat contre l'endpoint appelé ; état du consentement

Deux horloges

Les deux certificats expirent chacun à leur date, sont révocables chacun de leur côté, et se renouvellent séparément. Trois conséquences :

  • Deux alertes d'expiration, pas une. Un QWAC valide ne dit rien de l'état du QSealC, et réciproquement.
  • La rotation du QWAC touche les tokens. L'enregistrement OAuth2 survit si le DN du sujet ne change pas — c'est lui que tls_client_auth_subject_dn déclare — mais les access tokens liés à l'ancienne empreinte (RFC 8705) ne passent plus. Réémettre les tokens fait partie de la rotation.
  • La rotation du QSealC touche le keyId — l'URL suffixée de l'empreinte change, ou le x5t#S256 du profil JWS — et elle ne doit pas retirer l'ancien certificat : les requêtes déjà signées doivent rester vérifiables. C'est tout l'objet de la non-répudiation. On retire la clé privée, on laisse le certificat publié.

Pour résumer

  1. QWAC = couche TLS. Lu au handshake, par le composant qui ouvre ou termine la connexion. Sa clé vit là, nulle part ailleurs.
  2. QSealC = couche message. Lu à chaque requête, par un vérificateur qui doit voir les octets d'origine. Sa clé vit là où la requête est construite.
  3. STET : QWAC pour TLS 1.2 (§3.1–3.2), chaque requête signée avec le QSealC et 400 sinon (§3.5), profil JWS recommandé depuis la 1.6.3 (§3.5.2), identité OAuth2 portée par le QWAC (§3.9, RFC 8705).
  4. Pas de code HTTP → QWAC. 400 → QSealC. 401 → binding du token. 403 → ni l'un ni l'autre.
  5. Deux horloges : deux expirations, deux rotations, et l'ancien QSealC reste publié pour vérifier le passé.

Pour le reste de la stack — standards, flux SCA, consentement — voir Architecture technique d'une API DSP2. Les deux mécanismes de signature, octet par octet, et les pannes de handshake les plus fréquentes font l'objet des deux articles suivants. Le texte intégral de la section citée est dans le manuel STET 1.6.3, avec le PDF original en regard.

#dsp2#psd2#open-banking#sécurité#eidas#mtls#stet
Tendances

Articles à lire ensuite

Approfondissez le sujet avec ces articles sélectionnés.

7 avril 2026
technique

Architecture technique d'une API DSP2 : ce qu'il faut savoir avant d'écrire la première ligne de code — Lire l'article

Tour d'horizon technique de la DSP2 pour les CTO, dev et PM techniques : standards d'API, sécurité (mTLS, certificats eIDAS), OAuth2, flux SCA, gestion du consentement, pièges d'implémentation.

6 avril 2026
réglementation

Comprendre la PSD2 : ce qu'elle change pour vos clients et votre business — Lire l'article

Tout ce qu'un dirigeant, un product manager ou une équipe business doit comprendre de la PSD2 (DSP2). Acteurs, consentement, opportunités, sans jargon technique.