Verify a card independently
Check a card’s signed versions, its place in the log’s index and the witnesses behind the log.
A lookup or summary helps you find the card. Fetch the full card to get its proof. The normal card page and the widget already perform these checks in the reader’s browser. An integration that displays its own verified verdict needs to check the proof itself.
Read format in GET /v1/log before choosing the checks. The live log, log.veil.rip/staging-1, is in format 2, and a format 2 log also names the Veil organisation in staffOrg. Format 1 is frozen on log.veil.rip/test-1: it stays readable and takes no new versions.
Format 2: the index path#
A format 2 card brings what these checks need: proof for the current version, index for the card’s index bundle, authority for the versions that change who can sign, and current with the current label, body and signature. The work does not grow with the length of the card’s history.
- Check the checkpoint in
index.checkpoint.note: the log signature, the witness quorum from your trusted policy and its freshness.proofandindexrefer to that same checkpoint. - Verify
index.entry, the checkpoint’s last index entry, with its inclusion proof. Checkindex.valueagainst that entry’s root withindex.proof, then apply the entries ofindex.tailthat concern this card. - Check each item of
authorityfrom its log entry alone: its inclusion at positioni, its label hash against thecthatindex.value.authgives, and its signature by a key of the authority before it. Version 1 gives the card ID. FollowauthorityNextuntil it is null. - Check
current: its label hash is the one inindex.value.latest, a key of the authority in force signed it, the state shown has the root in its label, and the keys match the authority. - For an organisation, check the member that
label.signernames in each authority version and in the current one. That member held the role and signed with an active key of their own card at that log position. - Check the staff statements in
index.statements. The first isindex.value.standing, eachprevis theiof the next, and each one is signed by a member of the Veil organisation whose role allows its action. Read more pages fromstatementsNextuntil it is null. - A closed card answers 410 with
closed. Show it as closed only when that closing entry verifies.
veil-rubrica:identity-version:v2
<canonical label>
veil-rubrica:statement-entry:v2
<canonical entry without signature>
veil-rubrica:close-entry:v2
<canonical entry without signature>Keep the token, the ID, the last verified version and its authority. On the next visit, reject an index that points to an older version or that changes authority versions you already verified. A full check reads every version from GET /v1/identities/{n}/versions, starting at version 1, and verifies each body, signature and operation without the index.
A composite signature requires both Ed25519 and ML-DSA-65 to verify. Check freshness using enough valid witness signatures to satisfy the quorum. A stale quorum can prove history while leaving the current state uncertain.
Format 1 on test-1#
These steps apply only to a card served by a log in format 1, today the frozen log.veil.rip/test-1. Reject a format 1 card when GET /v1/log says format 2.
- Verify the record signature over the identity-version prefix followed by the exact proof.record bytes.
- Recompute SHA-256 over salt and record. It must equal proof.commitment. For version 1 it also determines the card ID and fingerprint.
- Check that proof.entry commits to this card’s token and commitment. Recompute the RFC 6962 leaf hash and follow the inclusion proof to the checkpoint root.
- Check the log signature against its expected key and require the witness quorum from your trusted policy. Count each witness key once.
- Verify the version chain, including prev, signing-key authority and every commitment back to version 1. Follow pagination cursors until the chain is complete.
- Keep the last accepted checkpoint and check consistency before accepting a newer one. Reject a rollback or a conflicting root at the same size.
veil-rubrica:identity-version:v1
Read log resources#
GET /v1/log identifies the log used by this directory. Log resources live under that origin’s HTTPS URL. The full vkey string also contains a key ID and public key data, so it is not a page address.
- GETRead the directory’s log stateIdentify the active log and read the checkpoint and witness state seen by the server.
/v1/log - GETRead a signed checkpointRead the log’s signed size and Merkle root.
/{log}/checkpoint - GETRead a witness policyRead the log key, witness keys and quorum rule.
/{log}/policy - GETRead witness cosignaturesRead each configured witness’s latest stored cosignature.
/{log}/witnesses - GETRead Merkle hash tilesRead C2SP hash tiles for inclusion and consistency proofs.
/{log}/tile/{level}/{index} - GETRead entry bundlesRead C2SP bundles of public log entries.
/{log}/tile/entries/{index}