Como funciona a verificação
Esta página usa o passaporte de demonstração ao vivo, não uma maquete. A primeira parte são cinco passos em linguagem simples: o que cada um faz e o que não estabelece. A segunda parte é a mesma checagem em forma de comandos, para quem prefere executá-la a ler sobre ela.
Os cinco passos
Baixe a credencial
Toda página de passaporte oferece a credencial como um token assinado, uma única linha de texto. Baixe-o. Tudo o que segue opera sobre esse arquivo, nunca sobre a página que o exibe.
Isso estabelece que você tem o mesmo artefato que o emissor publicou. Não estabelece que algo nele seja verdadeiro.
Verifique a assinatura do emissor
O token carrega uma assinatura sobre o seu conteúdo. Um verificador refaz a checagem com a chave pública do emissor; mude um caractere do conteúdo e a checagem falha.
Isso estabelece que o conteúdo não mudou desde que o detentor daquela chave o assinou. Não estabelece quem detém a chave: esse é o próximo passo.
Confira a identidade do emissor
O emissor é nomeado como did:web:anydpp.eu, que resolve para um documento público de identificação em anydpp.eu. A chave usada no passo dois precisa estar listada ali, sob o próprio nome e domínio do emissor.
Isso estabelece que a chave pertence a quem controla aquele domínio. Não estabelece que o dono do domínio seja, no mundo real, quem afirma ser.
Confira a lista de status
A credencial nomeia uma lista de status, publicada e assinada pelo mesmo emissor, e a própria posição nela. Leia o bit naquela posição: 0 significa não revogada, 1 significa revogada.
Isso estabelece se o emissor retirou a credencial desde a emissão. Não estabelece por quê, e não reconfere nada do que a credencial diz.
Inspecione as referências de evidência
A credencial lista os documentos de origem a partir dos quais foi construída, cada um por identificador e por um digest do registro, e nomeia o documento de origem por trás de cada atributo e seu nível de confiança. Ela não contém os documentos em si.
Isso estabelece quais documentos o emissor afirma ter lido, e permite a quem tem um deles provar que é o mesmo. Não estabelece que esses documentos sejam autênticos nem que seu conteúdo seja verdadeiro.
Como funciona a verificação
Do documento de origem até uma assinatura que um terceiro consegue conferir. O método, no nível em que o publicamos.
Este filme: produção assistida por IA, conteúdo verificado por pessoas. Locução sintética em inglês, legendas em cinco idiomas. Acessibilidade e transparência de IA
Transcrição
A passport is worth exactly what stands behind it.
Everything downstream of that is presentation.
Every attribute starts at a source document.
A check compares the published value against that document, deterministically.
The same document and the same rule always give the same answer, and a model never decides the fact.
The check does not return a verdict.
It returns a confidence level, and the reason for it.
A confidence level can be argued with.
A verdict can only be believed or not.
High confidence flows.
Low confidence stops, and it stops the whole passport rather than its own line, until a registered human attester resolves it under their own name.
Every step is written to a hash chain.
Change one entry and every entry after it stops matching, so tampering is detectable rather than deniable.
Nothing is deleted to make the record look better, because a deletion would break the same chain.
And then the part that matters.
A third party checks the credential's own signature, without access to AnyLAI's database.
The verifier resolves the issuer's public identifier document and checks the signature against it.
That is the step that does not rest on taking our word for it.
European rules place the final judgment with people who answer for it.
AnyDPP is built the same way. Where confidence is low, a named, registered professional decides, and the decision is recorded.
O que mudou
As primeiras credenciais de demonstração, emitidas em julho de 2026, carregavam uma prova rotulada Ed25519Signature2020 cujos bytes assinados não eram a forma canônica daquela suíte. Uma assinatura real, mas que nenhum verificador baseado em padrões aceitava, de modo que a única checagem disponível era a da própria AnyLAI. Esse formato de prova está descontinuado: os quatro passaportes que o carregam seguem legíveis como evidência histórica, marcados como tal, sem botão de verificação.
As credenciais de demonstração atuais são emitidas como um token assinado na forma que o padrão W3C (World Wide Web Consortium) de Verifiable Credentials define para provas envelopantes, com a chave do emissor publicada em did:web:anydpp.eu e uma lista de status assinada para revogação. Os passos acima e os comandos abaixo usam apenas esse token, essa chave e essa lista.
O que a verificação não estabelece
Uma verificação que passa em todos os passos acima responde a uma pergunta: esta é a credencial que o emissor publicou, e o emissor ainda a sustenta. Ela não responde a estas:
Três coisas diferentes são facilmente lidas como uma só: a autenticidade criptográfica, que os passos acima estabelecem; a verdade das fontes, que só os documentos e as pessoas por trás deles podem estabelecer; e a suficiência regulatória, que cabe ao operador que coloca as mercadorias no mercado e à autoridade competente.
- A verdade de cada afirmação num documento de origem. Um digest prova que um documento é o que foi lido, não que o que ele diz é exato.
- A conformidade legal. A credencial registra evidência e não emite veredito sobre se mercadorias podem ser colocadas em qualquer mercado.
- A completude da diligência devida. Ela lista os documentos que foram lidos, não os documentos que as obrigações do próprio operador ainda podem exigir.
- Uma certificação de qualquer tipo. Ninguém auditou o produtor, a gleba ou a remessa com base nesta credencial.
- Aprovação de regulador. Nenhuma autoridade competente revisou ou endossou a credencial, o emissor ou o método.
Para engenheiros: a mesma checagem, em comandos
Tudo abaixo roda sem repositório e sem conta: três downloads, um verificador de cerca de trinta linhas em Node ou Python, um teste de adulteração e os valores publicados para comparar. Os comandos não são traduzidos; um comando traduzido deixa de funcionar.
Copy and paste
1. Download the three artefacts
# 1. the credential, as a compact JWS (application/vc+jwt) curl -s https://anylai.eu/api/corridor/passports/DEMO26-000001/credential.jwt -o DEMO26-000001.jwt # 2. the issuer's DID document (the public key lives HERE, not in the credential) curl -s https://anydpp.eu/.well-known/did.json -o did.json # 3. the status list credential (an EnvelopedVerifiableCredential around its own JWS) curl -s https://anylai.eu/api/corridor/status-list/1 -o status-list-1.json # what you downloaded sha256sum DEMO26-000001.jwtThe credential is one line of text: header, payload and signature, base64url-encoded and dot-separated. The DID document is fetched from the issuer's own domain, never taken from inside the credential: a forged credential must not be allowed to vouch for itself.
2. Verify it in Node (one file, one dependency)
// verify.mjs -- npm i jose -- node verify.mjs import { compactVerify, importJWK } from "jose"; import { gunzipSync } from "node:zlib"; const b64 = (s) => Buffer.from(s, "base64url"); const jws = (await (await fetch("https://anylai.eu/api/corridor/passports/DEMO26-000001/credential.jwt")).text()).trim(); const header = JSON.parse(b64(jws.split(".")[0])); if (header.typ !== "vc+jwt" || header.cty !== "vc") throw new Error("not a vc+jwt"); const did = header.kid.split("#")[0]; const didDoc = await (await fetch(`https://${did.replace("did:web:", "")}/.well-known/did.json`)).json(); const method = didDoc.verificationMethod.find((m) => m.id === header.kid); if (!method || !didDoc.assertionMethod.includes(header.kid)) throw new Error("kid not under assertionMethod"); const key = await importJWK(method.publicKeyJwk, header.alg); const { payload } = await compactVerify(jws, key); // throws JWSSignatureVerificationFailed on a bad signature const vc = JSON.parse(Buffer.from(payload).toString("utf8")); if (vc.issuer.id !== method.controller) throw new Error("key controller is not the issuer"); console.log("signature: valid | issuer:", vc.issuer.id, "| kid:", header.kid); const wrapper = await (await fetch(vc.credentialStatus.statusListCredential)).json(); const listJws = wrapper.id.replace("data:application/vc+jwt,", ""); const listHeader = JSON.parse(b64(listJws.split(".")[0])); const listMethod = didDoc.verificationMethod.find((m) => m.id === listHeader.kid); const listKey = await importJWK(listMethod.publicKeyJwk, listHeader.alg); const list = JSON.parse(Buffer.from((await compactVerify(listJws, listKey)).payload).toString("utf8")); const encoded = list.credentialSubject.encodedList; if (!encoded.startsWith("u")) throw new Error("encodedList is not multibase base64url"); const bits = gunzipSync(b64(encoded.slice(1))); const index = Number(vc.credentialStatus.statusListIndex); const revoked = (bits[index >> 3] >> (7 - (index & 7))) & 1; console.log("status:", revoked ? "revoked" : "active", "| status list signature: valid");Steps two to four of the page above, as code. It throws on a bad signature, on a key that is not listed under the issuer's assertionMethod, on a controller that is not the issuer, and on a status list that is not signed by the same key.
3. Or in Python
# verify.py -- pip install pyjwt cryptography requests -- python verify.py import base64, gzip, json, jwt, requests jws = requests.get("https://anylai.eu/api/corridor/passports/DEMO26-000001/credential.jwt").text.strip() header = jwt.get_unverified_header(jws) assert header["typ"] == "vc+jwt" and header["cty"] == "vc" did = header["kid"].split("#")[0] did_doc = requests.get(f"https://{did.removeprefix('did:web:')}/.well-known/did.json").json() method = next(m for m in did_doc["verificationMethod"] if m["id"] == header["kid"]) assert header["kid"] in did_doc["assertionMethod"] key = jwt.algorithms.OKPAlgorithm.from_jwk(json.dumps(method["publicKeyJwk"])) vc = jwt.decode(jws, key=key, algorithms=["EdDSA"]) # raises InvalidSignatureError on a bad signature assert vc["issuer"]["id"] == method["controller"], "key controller is not the issuer" print("signature: valid | issuer:", vc["issuer"]["id"], "| kid:", header["kid"]) wrapper = requests.get(vc["credentialStatus"]["statusListCredential"]).json() list_jws = wrapper["id"].removeprefix("data:application/vc+jwt,") list_header = jwt.get_unverified_header(list_jws) list_method = next(m for m in did_doc["verificationMethod"] if m["id"] == list_header["kid"]) list_key = jwt.algorithms.OKPAlgorithm.from_jwk(json.dumps(list_method["publicKeyJwk"])) status_list = jwt.decode(list_jws, key=list_key, algorithms=["EdDSA"]) encoded = status_list["credentialSubject"]["encodedList"] assert encoded.startswith("u"), "encodedList is not multibase base64url" body = encoded[1:] bits = gzip.decompress(base64.urlsafe_b64decode(body + "=" * (-len(body) % 4))) index = int(vc["credentialStatus"]["statusListIndex"]) print("status:", "revoked" if bits[index // 8] >> (7 - index % 8) & 1 else "active", "| status list signature: valid")The same check with PyJWT and cryptography. Both verifiers are the reader's own code calling an open-source library; neither calls anything of AnyLAI's except the three public downloads.
4. Prove the check has teeth
// tamper.mjs -- change ONE character of the payload segment and the signature check must fail import { compactVerify, importJWK } from "jose"; const jws = (await (await fetch("https://anylai.eu/api/corridor/passports/DEMO26-000001/credential.jwt")).text()).trim(); const [h, p, s] = jws.split("."); const flipped = p.slice(0, 10) + (p[10] === "A" ? "B" : "A") + p.slice(11); const didDoc = await (await fetch("https://anydpp.eu/.well-known/did.json")).json(); const key = await importJWK(didDoc.verificationMethod[0].publicKeyJwk, "EdDSA"); await compactVerify(`${h}.${flipped}.${s}`, key) .then(() => { throw new Error("TAMPERED CREDENTIAL VERIFIED: stop trusting this check"); }) .catch((e) => console.log("tampered credential rejected:", e.code ?? e.message));Feed a credential with one character of its payload changed to the same verifier. If it still passes, the verification is not doing anything and you should stop trusting it. That is the test worth running first.
Published values
| Credential (compact JWS) | https://anylai.eu/api/corridor/passports/DEMO26-000001/credential.jwt |
|---|---|
| Credential (JSON-LD envelope) | https://anylai.eu/api/corridor/passports/DEMO26-000001/credential.jsonld |
| DID document | https://anydpp.eu/.well-known/did.json |
| Status list | https://anylai.eu/api/corridor/status-list/1 |
| kid | did:web:anydpp.eu#key-1 |
| alg / typ / cty | EdDSA / vc+jwt / vc |
| Expected outcome | signature valid; kid under assertionMethod; controller = issuer; status active |
| SHA-256 of DEMO26-000001.jwt | published in the release record |
The digest is read from the live passport API when this page is viewed, so it names the artefact actually being served; compare it with the output of sha256sum above.
O radar regulatório, uma vez por mês
O que realmente mudou nas regras europeias de desmatamento e de passaporte de produto, com fonte para cada item e mais nada no envelope.
Confirmação dupla: você confirma clicando em um link na sua caixa de entrada, e sai com um clique a partir de qualquer edição.
Faça você mesmo
O passaporte de demonstração é público. A credencial dele pode ser checada contra a chave do emissor publicada em did:web:anydpp.eu com os comandos desta página, sem conta.
