DCQL explicado: como um verificador pede a uma carteira exatamente o que precisa
A Digital Credentials Query Language, DCQL, é o formato de consulta JSON que o OpenID4VP utiliza num pedido de apresentação. Permite a uma parte confiante descrever que credenciais, e que atributos dessas credenciais, pretende ver, de uma forma que qualquer carteira conforme consegue interpretar sem uma integração à medida.
O problema que o DCQL resolve
Uma carteira empresarial pode guardar credenciais em vários formatos: um registo comercial em SD-JWT VC, uma qualificação profissional codificada em mdoc, uma credencial verificável W3C de um piloto anterior. Um verificador que apenas precisa de confirmar um número de registo e uma denominação social não tem uma forma portável de pedir exatamente isso, independentemente do formato, sem aceitar a credencial completa ou programar manualmente um pedido separado por formato e por fornecedor de carteira.
O DCQL resolve o lado do pedido dessa lacuna. É um único objeto JSON, incorporado no pedido de autorização OpenID4VP, que indica uma ou mais consultas de credenciais, cada uma associada a um formato e a um conjunto de caminhos de atributos. A carteira avalia a consulta face às credenciais guardadas, determina quais correspondem e só então pede ao titular que aprove a divulgação desses atributos concretos. O verificador recebe uma estrutura previsível para processar, seja qual for a carteira usada pelo titular.
1. Verificador
Envia um pedido OpenID4VP com uma dcql_query
2. Carteira
Compara a consulta com as credenciais guardadas
3. Titular
Aprova a divulgação apenas dos atributos pedidos
4. Verificador
Recebe uma apresentação por id de consulta de credencial
A forma de uma consulta DCQL
Uma consulta DCQL é um objeto JSON com um array credentials e, opcionalmente, um array credential_sets. Cada entrada de credentials é uma consulta de credencial. Os campos marcados com M são obrigatórios nessa consulta.
dcql_query
credentials[ ]
Uma consulta por cada credencial de que precisa
id + format
Que credencial, em que formato
meta
Filtro de tipo, como vct_values
claims[ ]
Caminhos dos atributos a divulgar
claim_sets[ ]
Combinações de atributos aceites
credential_sets[ ]
Opcional: que combinações de consultas de credenciais satisfazem o pedido
| Campo | Tipo | Obrigatório |
|---|---|---|
| id | string | M |
| format | enum: dc+sd-jwt | mso_mdoc | jwt_vc_json | ldp_vc | M |
| meta | objeto, a forma depende do formato | |
| claims | array de consultas de atributos | |
| claim_sets | array de arrays de ids de atributos | |
| trusted_authorities | array de objetos com um type e values |
Cada entrada de claims é, por sua vez, um objeto: um id usado para a referenciar a partir de claim_sets, um path, isto é, um array que localiza o atributo dentro da credencial (por exemplo ["legal_name"] para um atributo SD-JWT de primeiro nível, ou ["org", "registration_number"] para um atributo aninhado), e, opcionalmente, values, uma lista de valores com os quais o atributo tem de corresponder.
Exemplo prático: verificação de um registo comercial
Registo comercial
dc+sd-jwtO verificador diz: é isto que quero receber
- ✓ Número de registoreg_nopath: ["registration_number"]
- ✓ Denominação sociallegal_namepath: ["legal_name"]
- ✓ País de registoreg_countrypath: ["registration_country"]
{
"credentials": [
{
"id": "company_registration",
"format": "dc+sd-jwt",
"meta": {
"vct_values": ["urn:eudi:business:company-registration:1"]
},
"claims": [
{ "id": "reg_no", "path": ["registration_number"] },
{ "id": "legal_name", "path": ["legal_name"] },
{ "id": "reg_country", "path": ["registration_country"] }
]
}
]
}Exemplo de resposta da carteira
A carteira responde com um objeto vp_token indexado pelo id da consulta de credencial. Cada valor é um array de apresentações. Para dc+sd-jwt, uma apresentação é o JWT assinado pelo emissor, uma disclosure por cada atributo divulgado e um JWT de key binding que a associa ao nonce e ao cliente deste pedido.
O que a carteira envia
{
"vp_token": {
"company_registration": [
"<issuer-signed JWT>~<disclosure: registration_number>~<disclosure: legal_name>~<disclosure: registration_country>~<key binding JWT>"
]
}
}Atributos que o verificador vê após a validação
{
"vct": "urn:eudi:business:company-registration:1",
"registration_number": "12345678",
"legal_name": "Example Logistics B.V.",
"registration_country": "NL"
}Pedir uma alternativa: claim_sets
claim_sets lista grupos de ids de atributos por ordem de preferência. A carteira devolve o primeiro grupo que consegue satisfazer integralmente com o que o titular efetivamente tem, evitando que o verificador tenha de enviar dois pedidos separados, um para o caso preciso e outro para o caso alternativo.
Exemplo prático: número de registo ou, em alternativa, apenas a denominação social
1. Preferido
Devolvido quando a credencial contém ambos os atributos
2. Alternativa
Devolvido apenas quando o primeiro conjunto não pode ser satisfeito
{
"credentials": [
{
"id": "company_registration",
"format": "dc+sd-jwt",
"meta": { "vct_values": ["urn:eudi:business:company-registration:1"] },
"claims": [
{ "id": "reg_no", "path": ["registration_number"] },
{ "id": "legal_name", "path": ["legal_name"] }
],
"claim_sets": [
["reg_no", "legal_name"],
["legal_name"]
]
}
]
}Aqui o verificador prefere um número de registo juntamente com a denominação social, mas aceita apenas a denominação social se a credencial do titular não contiver um atributo de número de registo.
Exemplo de resposta: foi usada a alternativa
O que a carteira envia
{
"vp_token": {
"company_registration": [
"<issuer-signed JWT>~<disclosure: legal_name>~<key binding JWT>"
]
}
}Atributos que o verificador vê após a validação
{
"vct": "urn:eudi:business:company-registration:1",
"legal_name": "Example Logistics B.V."
}A credencial do titular não tem número de registo, por isso a carteira satisfez o segundo conjunto de atributos e divulgou uma única disclosure. A resposta não indica que conjunto foi usado: o verificador deduz isso a partir dos atributos que recebe.
Combinar credenciais: credential_sets
credential_sets funciona um nível acima de claim_sets. Cada entrada lista options, em que cada opção é um grupo de ids de consultas de credenciais. A carteira tem de satisfazer uma opção de cada entrada obrigatória, o que dá ao verificador lógica AND e OR entre credenciais num único pedido.
Obrigatório
Registo comercial
Um de
Registo de IVA
Um de
Atestado de conta bancária
"credential_sets": [
{ "options": [["company_registration"]] },
{ "options": [["vat_registration"], ["bank_account"]] }
]Exemplo de resposta: registo mais conta bancária
O que a carteira envia
{
"vp_token": {
"company_registration": [
"<issuer-signed JWT>~<disclosures>~<key binding JWT>"
],
"bank_account": [
"<issuer-signed JWT>~<disclosures>~<key binding JWT>"
]
}
}Atributos que o verificador vê após a validação
{
"company_registration": {
"vct": "urn:eudi:business:company-registration:1",
"registration_number": "12345678",
"legal_name": "Example Logistics B.V."
},
"bank_account": {
"vct": "urn:eudi:business:bank-account:1",
"iban": "NL91ABNA0417164300",
"account_holder": "Example Logistics B.V."
}
}O titular não tem uma credencial de registo de IVA, por isso a carteira escolheu a segunda opção do segundo conjunto. Os ids de consulta que não foram usados, neste caso vat_registration, simplesmente não aparecem em vp_token.
Apenas emissores de confiança: trusted_authorities
trusted_authorities restringe uma consulta de credencial a credenciais cujo emissor é suportado por uma autoridade em que o verificador confia. Cada entrada tem um type e uma lista de values: aki para um identificador de chave da autoridade, etsi_tl para uma lista de confiança ETSI, ou openid_federation para uma âncora de confiança de federação. A carteira só propõe credenciais que correspondam.
Exemplo prático: um registo de um emissor listado
O verificador diz: apenas de emissores desta lista de confiança
https://ec.europa.eu/tools/lotl/eu-lotl.xml
Credencial de registo de um emissor listado
o emissor consta da lista de confiança
✓ Corresponde à consulta
Credencial de registo de um emissor não listado
o emissor não consta da lista de confiança
✗ Não corresponde, não é proposta ao titular
{
"credentials": [
{
"id": "company_registration",
"format": "dc+sd-jwt",
"meta": { "vct_values": ["urn:eudi:business:company-registration:1"] },
"trusted_authorities": [
{
"type": "etsi_tl",
"values": ["https://ec.europa.eu/tools/lotl/eu-lotl.xml"]
}
],
"claims": [
{ "id": "reg_no", "path": ["registration_number"] },
{ "id": "legal_name", "path": ["legal_name"] }
]
}
]
}Exemplo de resposta: apenas a credencial do emissor listado
O que a carteira envia
{
"vp_token": {
"company_registration": [
"<issuer-signed JWT>~<disclosure: registration_number>~<disclosure: legal_name>~<key binding JWT>"
]
}
}Atributos que o verificador vê após a validação
{
"vct": "urn:eudi:business:company-registration:1",
"registration_number": "12345678",
"legal_name": "Example Logistics B.V."
}O titular tinha também uma credencial de registo de um emissor não listado, mas a carteira não a propôs. trusted_authorities é um filtro para a carteira, não uma garantia: o verificador continua a confirmar o emissor na lista de confiança quando valida a apresentação.
Corresponder a um valor: claims.values
Uma consulta de atributo pode incluir values, uma lista de strings, inteiros ou booleanos. A carteira só devolve o atributo quando o seu tipo e valor correspondem exatamente a um deles, pelo que um verificador pode verificar uma condição sem ter de pedir primeiro qualquer outra informação.
Exemplo prático: apenas empresas registadas nos Países Baixos ou na Bélgica
O verificador diz: apenas empresas registadas num destes países
Empresa neerlandesa
registration_country: "NL"
✓ Corresponde à consulta
Empresa alemã
registration_country: "DE"
✗ Não corresponde, não é proposta ao titular
{
"credentials": [
{
"id": "company_registration",
"format": "dc+sd-jwt",
"meta": { "vct_values": ["urn:eudi:business:company-registration:1"] },
"claims": [
{ "id": "legal_name", "path": ["legal_name"] },
{
"id": "reg_country",
"path": ["registration_country"],
"values": ["NL", "BE"]
}
]
}
]
}Exemplo de resposta: uma empresa neerlandesa
O que a carteira envia
{
"vp_token": {
"company_registration": [
"<issuer-signed JWT>~<disclosure: legal_name>~<disclosure: registration_country>~<key binding JWT>"
]
}
}Atributos que o verificador vê após a validação
{
"vct": "urn:eudi:business:company-registration:1",
"legal_name": "Example Logistics B.V.",
"registration_country": "NL"
}A credencial de uma empresa alemã tem registration_country "DE", por isso não satisfaz a consulta e a carteira não tem nada a devolver para ela. O verificador deve, ainda assim, verificar o valor nos atributos validados em vez de confiar na filtragem da carteira.
Restrições específicas de formato em meta
SD-JWT VC: vct_values
Para dc+sd-jwt, meta.vct_values lista os identificadores de tipo de credencial que o verificador aceita. Uma consulta só corresponde a uma credencial guardada cujo vct seja um dos valores listados, pelo que um verificador que apenas confia no tipo de credencial de registo de um emissor lista exatamente esse identificador.
mso_mdoc: doctype_value e namespace
Para mso_mdoc, meta.doctype_value fixa o DocType ISO 18013-5, e cada caminho de atributo começa pelo namespace mdoc a que o atributo pertence, em vez de um simples nome de campo, uma vez que o mdoc agrupa os atributos por namespace e não num objeto plano.
O ponto de situação do DCQL
- O DCQL é definido dentro da própria especificação OpenID4VP, e não num documento separado, e faz parte do rascunho desde que o mecanismo foi introduzido para substituir uma dependência anterior do DIF Presentation Exchange nos pedidos OpenID4VP.
- O EUDI Wallet Architecture and Reference Framework especifica o OpenID4VP como protocolo de apresentação e, com ele, o DCQL como o mecanismo de consulta que se espera que as partes confiantes e as carteiras do ecossistema suportem.
- As implementações de referência de carteiras e verificadores no programa EUDI Wallet Reference Implementation convergiram para o DCQL, pelo que as novas integrações de carteiras empresariais desenvolvidas hoje sobre OpenID4VP devem assumir o DCQL, e não o Presentation Exchange, como formato de consulta para pedidos de apresentação.
Termos relacionados
Perguntas frequentes
Em que difere o DCQL do DIF Presentation Exchange?
Ambos descrevem o que um verificador pretende obter de uma carteira, mas o DCQL está circunscrito ao OpenID4VP e é definido diretamente nessa especificação, enquanto o Presentation Exchange é uma especificação DIF autónoma que abrange também outros protocolos. O DCQL é propositadamente mais pequeno: não tem grupos de input descriptors nem submission requirements, e exprime restrições específicas de formato, como um doctype mdoc ou um tipo SD-JWT VC, diretamente num objeto de consulta, em vez de através de um filtro JSON Schema genérico. O ecossistema EUDI Wallet normalizou o uso do DCQL para apresentações OpenID4VP.
Uma consulta DCQL pode pedir mais do que uma credencial?
Sim. O array credentials pode listar várias consultas de credenciais, cada uma com o seu próprio id. Uma carteira que tenha correspondências para todas as entradas devolve uma apresentação por entrada. O objeto opcional credential_sets pode, além disso, exigir combinações específicas, por exemplo aceitar apenas uma credencial de registo comercial ou uma credencial de registo comercial juntamente com uma declaração de UBO, sem pedir duas vezes ao titular.
Que problema resolvem os claim_sets dentro de uma única consulta de credencial?
Uma credencial nem sempre contém todos os atributos que um verificador gostaria de receber. claim_sets lista grupos alternativos de ids de atributos, cada um suficiente por si só para satisfazer o pedido, ordenados do mais para o menos preferido. A carteira escolhe o primeiro grupo que consegue satisfazer integralmente com os atributos que o titular efetivamente tem, pelo que um verificador pode pedir um número de identificação preciso quando disponível e recorrer a uma verificação menos detalhada, como um indicador de maioridade, sem enviar dois pedidos separados.
O DCQL é específico da EUDI Wallet?
Não. O DCQL faz parte da especificação principal do OpenID4VP e qualquer implementação de OpenID4VP pode utilizá-lo. O ecossistema EUDI Wallet é um adotante de destaque: o Architecture and Reference Framework especifica o OpenID4VP com DCQL como mecanismo de apresentação que as partes confiantes têm de suportar, e é por isso que é particularmente relevante para carteiras e verificadores desenvolvidos para o mercado europeu.
O DCQL realiza, por si só, a divulgação seletiva?
Não. O DCQL apenas descreve o que está a ser pedido. Se a carteira consegue revelar exatamente esses atributos e nada mais depende do formato da credencial: tanto um SD-JWT VC como um ISO mdoc permitem divulgar um subconjunto dos seus atributos, pelo que um array claims do DCQL tira partido desse suporte. Uma consulta DCQL sobre um formato sem divulgação seletiva continuaria a funcionar, mas o titular teria de divulgar a credencial completa para satisfazer até uma consulta de um único atributo.
Fontes
Esta página tem caráter meramente informativo e não constitui aconselhamento jurídico. Para orientações oficiais, consulte diretamente a OpenID Foundation e a Comissão Europeia.