Os dois certificados saem do mesmo eIDAS TSP, carregam o mesmo número de autorização e os mesmos papéis DSP2, e muitas vezes chegam no mesmo pedido de compra. A diferença não está no que eles contêm. Está na camada da pilha que os lê. O QWAC é lido pela camada TLS, uma vez, no handshake. O QSealC é lido pela camada aplicativa, a cada requisição, em um cabeçalho HTTP.
Um ticket que diz “erro de certificado” sem dizer em qual camada não é diagnosticável. Este artigo não redefine os dois objetos — os verbetes QWAC, QSealC e mTLS fazem isso. Ele coloca cada um na pilha, na infraestrutura e nos logs, com o texto do STET 1.6.3 lado a lado. Para o panorama completo do stack, leia antes Arquitetura técnica de uma API DSP2.
Em uma imagem: duas camadas, dois certificados
Uma requisição DSP2 desce a pilha. Cada certificado só intervém em um único nível.
| QWAC | QSealC | |
|---|---|---|
| Base eIDAS | certificado qualificado de autenticação de site, art. 3(39) | certificado qualificado de selo eletrônico, art. 3(30) |
| Camada | transporte (TLS) | mensagem (HTTP) |
| Lido por | a pilha TLS dos dois lados, no handshake | o verificador de assinatura do ASPSP, a cada requisição |
| Frequência | uma vez por conexão | uma vez por requisição — e por resposta, se o ASPSP assinar |
| Sobrevive a um proxy que termina o TLS | não | sim |
| Valor probatório a posteriori | nenhum: nada é conservado | a assinatura fica na requisição, verificável depois |
| Chave privada, do lado do TPP | onde a conexão de saída é aberta | onde a requisição é construída |
| Sintoma quando quebra | handshake rompido, nenhum código HTTP | HTTP 400 (STET §3.5) |
| O que o STET diz a respeito | §3.1, §3.2, §3.9 | §3.5 |
A RTS (UE) 2018/389, art. 34, autoriza um ou outro para a identificação. Os padrões de API resolveram a questão empilhando os dois: STET e Berlin Group exigem o QWAC para o canal e o QSealC para a assinatura. Dois certificados, portanto duas chaves privadas, duas datas de expiração e dois procedimentos de rotação.
O que o STET exige, com o texto na mão
Três trechos do Framework 1.6.3 (Part 1) bastam. As páginas são as do PDF oficial, que o manual exibe na margem de cada parágrafo.
§3.1 e §3.2 — o QWAC, para o TLS e nada mais
"Each actor must be provided with at least one eIDAS certificate (QWAC), for TLS 1.2 purpose" (§3.1, p. 17). O TPP verifica o QWAC de servidor do ASPSP e apresenta o seu; os dois respeitam a ETSI TS 119 495; "in case of authentication failure, on one side or the other, the connection must be closed"; e "no additional encrypting or authenticating feature is required" (§3.2, p. 17–18). O QWAC nunca chega à requisição: tudo o que tem a dizer, ele diz no handshake.
O mesmo parágrafo fixa o formato do organizationIdentifier do sujeito do certificado: PSD, o código do país da NCA, um hífen, o identificador da NCA, um hífen, o número de autorização — PSDFR-ACPR-12345 para um ator autorizado pela ACPR. É esse campo, junto com os papéis do QC statement ETSI, que o ASPSP lê no certificado de cliente para saber quem chama, e em que qualidade.
§3.5 — o QSealC, para assinar cada requisição
"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).
O mecanismo histórico é o HTTP Signature na versão draft-cavage: um Digest SHA-256 do corpo, depois uma assinatura RSA-SHA256 feita com o QSealC sobre (request-target), Date, Content-Type, Content-Length, X-Request-Id, os cabeçalhos PSU-* e o próprio Digest, transportada no cabeçalho Signature com keyId, algorithm e a lista dos cabeçalhos assinados (§3.5.1.1, p. 53–55). O keyId é ou o identificador atribuído no registro OAuth2, ou a URL do QSealC com o sufixo _ seguido da sua impressão digital SHA-256 (§3.5.1.2, p. 55).
Desde a 1.6.3, o Framework recomenda substituir esse mecanismo pelo perfil JSON Web Signature do Open Banking Europe: um JWS destacado (RFC 7515) no cabeçalho x-jws-signature, cujo cabeçalho protegido carrega em x5t#S256 a impressão digital do QSealC signatário e em sigD a lista dos cabeçalhos cobertos (§3.5.2, p. 55–56). O draft-cavage, por sua vez, foi substituído no IETF pela RFC 9421 — que o STET não cita como alvo.
§3.9 — o QWAC volta uma terceira vez, no OAuth2
"Based on MTLS, the identity of the TPP is provided by its eIDAS certificate during OAuth2 procedures", com remissão à RFC 8705 (§3.9, p. 59). O servidor de autorização autentica, portanto, o cliente por tls_client_auth — o QWAC apresentado no handshake do POST /token — e pode vincular o token emitido a esse certificado, pela claim cnf e pela impressão digital x5t#S256. Um token vinculado a uma impressão digital que já não é a apresentada é recusado, mesmo que não tenha expirado.
Uma requisição, três verificações
Três verificações, três camadas, três sintomas que não se parecem. A ordem das duas verificações aplicativas é própria de cada banco; o sintoma, esse, não muda.
Onde vivem as chaves privadas: o erro de camada
É aqui que se erra. As duas chaves privadas não vivem no mesmo lugar, porque os dois certificados não são lidos pelo mesmo componente.
Do lado do TPP, na saída
A chave do QSealC pertence ao componente que constrói a requisição, porque a assinatura cobre cabeçalhos — Date, Content-Length, X-Request-Id — que precisam estar congelados antes do envio. A chave do QWAC pertence ao componente que abre a conexão. Se um proxy de saída, um NAT aplicativo ou um service mesh abre as conexões no lugar da aplicação, é ele que apresenta o QWAC, e a aplicação não tem por que guardar a chave. Colocar a chave do QWAC na aplicação quando o mesh termina e reabre o TLS resulta em um handshake sem certificado de cliente: um alerta TLS, e nenhum código HTTP.
Do lado do ASPSP, na entrada
Do lado do banco, o QWAC de cliente para no componente que termina o TLS. O que passa dali em diante é uma identidade extraída — organizationIdentifier, papéis, impressão digital — transmitida em um cabeçalho interno no qual o resto da cadeia precisa poder confiar, daí o interesse em assiná-lo ou em aceitá-lo apenas do terminador. A assinatura QSealC, por sua vez, atravessa tudo: um componente situado em qualquer ponto atrás pode verificá-la, desde que veja os bytes originais. Um gateway que reserializa o JSON, recalcula o Content-Length ou normaliza o Date antes do verificador produz 400 em requisições válidas.
As seis confusões de camada
| # | Confusão | O que acontece | Sintoma |
|---|---|---|---|
| 1 | Chave do QWAC em um componente que não abre a conexão | handshake sem certificado de cliente | alerta TLS, sem HTTP |
| 2 | QSealC apresentado como certificado de cliente TLS, ou QWAC usado para assinar | o QcType ETSI não é o correto (web para um, eseal para o outro); um verificador que o confere recusa | alerta TLS, ou 400 |
| 3 | Assinatura calculada antes de um proxy que reescreve Date, Content-Length ou o corpo | a assinatura cobre bytes diferentes dos recebidos | 400, assinatura inválida |
| 4 | Verificação feita depois de uma transformação da requisição, do lado do ASPSP | mesma causa, em espelho | 400 em requisições válidas |
| 5 | QWAC renovado sem reemitir os tokens vinculados | cnf.x5t#S256 já não corresponde ao certificado apresentado | 401 em um token não expirado |
| 6 | AC do QTSP do banco ausente do trust store do TPP | o TPP recusa o QWAC de servidor do ASPSP | unknown_ca, conexão fechada pelo próprio TPP |
A confusão 2 é a mais cara, porque é invisível enquanto o banco não confere o tipo de certificado — e visível de uma vez no dia em que ele passa a conferir. Os dois certificados costumam ser vendidos juntos; não são intercambiáveis.
Matriz de diagnóstico
| Sintoma | Camada | Certificado em questão | Onde olhar |
|---|---|---|---|
Conexão fechada durante o handshake, nenhum código HTTP; handshake_failure, bad_certificate, certificate_expired, unknown_ca | TLS | QWAC — o seu, ou o do banco que você não reconhece | logs do terminador TLS; openssl s_client -cert -key |
| 401 | token | QWAC, pelo binding RFC 8705; ou simplesmente um token expirado | resposta do servidor de autorização; cnf do token contra a impressão digital do certificado apresentado |
| 400 mencionando a assinatura (STET §3.5) | mensagem HTTP | QSealC | Digest recalculado; lista dos cabeçalhos assinados; keyId resolvível; bytes realmente enviados |
| 403, ou código de negócio do banco | autorização | nenhum dos dois | papéis PSD2 do certificado contra o endpoint chamado; estado do consentimento |
Dois relógios
Os dois certificados expiram cada um na sua data, são revogáveis cada um do seu lado e se renovam separadamente. Três consequências:
- Dois alertas de expiração, não um. Um QWAC válido não diz nada sobre o estado do QSealC, e vice-versa.
- A rotação do QWAC afeta os tokens. O registro OAuth2 sobrevive se o DN do sujeito não mudar — é ele que
tls_client_auth_subject_dndeclara — mas os access tokens vinculados à impressão digital antiga (RFC 8705) deixam de passar. Reemitir os tokens faz parte da rotação. - A rotação do QSealC afeta o
keyId— a URL com o sufixo da impressão digital muda, ou ox5t#S256do perfil JWS — e ela não deve retirar o certificado antigo: as requisições já assinadas precisam continuar verificáveis. É todo o sentido do não repúdio. Retira-se a chave privada, deixa-se o certificado publicado.
Para resumir
- QWAC = camada TLS. Lido no handshake, pelo componente que abre ou termina a conexão. Sua chave vive ali, e em nenhum outro lugar.
- QSealC = camada de mensagem. Lido a cada requisição, por um verificador que precisa ver os bytes originais. Sua chave vive onde a requisição é construída.
- STET: QWAC para o TLS 1.2 (§3.1–3.2), cada requisição assinada com o QSealC e 400 caso contrário (§3.5), perfil JWS recomendado desde a 1.6.3 (§3.5.2), identidade OAuth2 carregada pelo QWAC (§3.9, RFC 8705).
- Sem código HTTP → QWAC. 400 → QSealC. 401 → binding do token. 403 → nem um nem outro.
- Dois relógios: duas expirações, duas rotações, e o QSealC antigo continua publicado para verificar o passado.
Para o resto do stack — padrões, fluxos SCA, consentimento — veja Arquitetura técnica de uma API DSP2. Os dois mecanismos de assinatura, byte a byte, e as falhas de handshake mais frequentes são o assunto dos dois artigos seguintes. O texto integral da seção citada está no manual STET 1.6.3, com o PDF original lado a lado.