The adversarial corpus, public. These are the
Wycheproof-style conformance vectors every Attest verifier — browser JavaScript,
stdlib Python, and AWS Lambda — must judge identically. Each row ships
the real exported pack; verify → opens the browser verifier on it.
A verifier that disagrees with the expected verdict is wrong, whatever surface it
runs on. Five more vectors exercise issuer-document pinning and need a companion
trust document — they live in the repo's tests/vectors/.
Verifier conformance vectors
The interesting rows aren't the obvious tampers — they're the grammar
traps: leaf_index: true (a bool is an int subclass in Python, not an
integer in JSON), "5" as a string, 5.5 fractional indices,
-1 indices and tree sizes (real JSON integers — the type check accepts
them; the range guard is the load-bearing branch), space-padded hex, a tree_size
of 240 that kills JS bitwise ops. These are
the cases where two verifiers silently diverge — the corpus exists so ours can't.
Expected: PASS (16)
| vector | oracle | what it exercises | verify |
|---|---|---|---|
ok-chain-case-roots | must PASS | two members carry the SAME head at one size, spelled upper- and lower-case — one head, not a collision; every surface dedupes on the decoded root | verify → |
ok-chain-quoted-bridge | must PASS | a member's signed extends.first spelled as a digit string — signed material is evaluated with JS-mirrored coercion, so the quoted hop is legal on every surface | verify → |
ok-checkpoint-chain | must PASS | the pack embeds prior signed checkpoint heads — each verified under the issuer lineage so two exports can reconcile non-adjacent heads offline, hop-by-hop | verify → |
ok-clean-bundle | must PASS | one visit, one key, media digests all present — the baseline | verify → |
ok-decoy-successor-order | must PASS | a consented decoy successor listed FIRST in key_rotations.json — only the highest-sequence consented pivot (K_A->K_B) may inherit trust; a first-match-in-pool verifier would pick the attacker and fail this pack | verify → |
ok-embedded-monitor-trail | must PASS | monitor_observation receipts embedded in the checkpoint doc — each verified under the issuer lineage and proven inside the signed head, so the watch trail travels with the pack | verify → |
ok-float-leaf-index | must PASS | leaf_index spelled 5.0 — JSON keeps no int/float distinction, so Number.isInteger parity means every verifier accepts integral floats identically | verify → |
ok-float-tree-size | must PASS | a properly SIGNED head claiming tree_size 5.0 — the signature verifies on the literal bytes, and Number.isInteger parity means integral floats verify identically everywhere | verify → |
ok-forged-cosig-ignored | must PASS | a cosig attesting a DIFFERENT head (or one whose signature fails after the edit) counts as absent — the pack still verifies on its own proofs; auxiliary attestations report honestly, never gate | verify → |
ok-grafted-revocation | must PASS | a self-signed key_revocation grafted into key_rotations.json is inert twice over — it can't join the signed trust walk, and foreign-signed receipts owe no log proof so the graft can't kill the pack either | verify → |
ok-legacy-no-manifest | must PASS | a pre-pin pack still verifies — the manifest is optional when absent, mandatory when present | verify → |
ok-redacted-media | must PASS | media bytes withheld by redaction; signed digests still verify | verify → |
ok-revoked-case | must PASS | revocation annotates: records + the pivot receipt itself sit in the suspect window | verify → |
ok-rotated-case | must PASS | case pack spanning a signed rotation — predecessor pin verifies both eras | verify → |
ok-witness-anchored | must PASS | the witness's attestation is itself committed to the witness's own transparency log — the pack proves the cosignature was published, not just signed and handed over | verify → |
ok-witness-cosigned | must PASS | an independent witness's counter-signature rides the checkpoint doc — verified under its own key, reported as an auxiliary attestation, never a gate | verify → |
Expected: FAIL (28)
| vector | oracle | what it exercises | verify |
|---|---|---|---|
fail-anchor-proof-graft | must FAIL | a packed anchor whose cosig cannot reach the anchor's signed head — a claimed anchor is either verifiable or a lie; every verifier fails closed | verify → |
fail-bool-leaf-index | must FAIL | leaf_index true — bool is an int subclass in Python but not an integer in JSON; Number.isInteger parity rejects it | verify → |
fail-chain-dup-size | must FAIL | two issuer-signed heads at one tree size inside a single document is a fork claim the reconcile cannot read honestly — the pack refuses it at verification time | verify → |
fail-chain-foreign-member | must FAIL | a chain member signed by a foreign key — the walk could never trust a bridge it names, so the pack fails closed | verify → |
fail-chain-nonhex-root | must FAIL | a 64-char non-hex member root — the strictest spelling wins on every surface, so the pack fails closed at intake instead of diverging mid-walk | verify → |
fail-doctored-verifier | must FAIL | a post-export edit to verify_case.py — membership checks names, only the signed pin checks the bytes | verify → |
fail-embedded-foreign-receipt | must FAIL | an embedded receipt signed outside the issuer lineage — embedded evidence must bind the pack's issuer or it is grafted testimony | verify → |
fail-embedded-tampered-receipt | must FAIL | an embedded receipt's payload flipped — payload hash and signature both fail; a doctored observation can never ride the signed head | verify → |
fail-foreign-pin | must FAIL | a valid pin receipt under an untrusted key — signature integrity is not issuer authority | verify → |
fail-forged-verifier-tool | must FAIL | a modified verify_bundle.py fails its own signed pin — membership whitelists names, only the manifest pins bytes | verify → |
fail-fractional-leaf-index | must FAIL | leaf_index 5.5 — non-integral indices are not integers on any surface; Python must not silently truncate where JS rejects | verify → |
fail-grafted-log-proof | must FAIL | another receipt's audit path grafted on — the Merkle math catches what a presence check never would | verify → |
fail-grafted-pin | must FAIL | a verifier_manifest signed for another pack cannot pin this one — the scope binding stops the replay | verify → |
fail-media-mismatch | must FAIL | media bytes that don't hash to the signed digest are caught | verify → |
fail-missing-listed | must FAIL | a bundle the signed manifest lists but the zip lacks fails | verify → |
fail-missing-log-proof | must FAIL | a pack receipt silently dropped from log_checkpoint.json — the pack cannot claim log membership it does not prove | verify → |
fail-missing-pinned-tool | must FAIL | a tool the signed pin names but the pack lacks fails — the pin binds both directions | verify → |
fail-negative-leaf-index | must FAIL | leaf_index -1 — Number.isInteger(-1) is TRUE, so this isolates the explicit index<0 range guard every surface must carry beyond the type check | verify → |
fail-negative-tree-size | must FAIL | a properly SIGNED head claiming tree_size -1 — Number.isInteger(-1) is TRUE, so this isolates the size<1 range guard: a log with negative size is a malformed head everywhere | verify → |
fail-orphan-rotation | must FAIL | a rotation the successor never countersigned cannot pivot trust | verify → |
fail-oversize-tree-size | must FAIL | a properly SIGNED head claiming tree_size 2^40 — valid signature, impossible size: JS bitwise ops die past 2^31, so every surface rejects it rather than diverging | verify → |
fail-payload-tamper | must FAIL | a flipped payload field breaks the signed hash | verify → |
fail-signature-tamper | must FAIL | a corrupted signature must never verify | verify → |
fail-smuggled-member | must FAIL | a member the pack format doesn't name fails closed | verify → |
fail-spaced-hex-proof | must FAIL | a proof node spelled with spaces between byte pairs — Python bytes.fromhex tolerates whitespace where strict hex rejects; every surface now fails closed identically | verify → |
fail-string-leaf-index | must FAIL | leaf_index as a quoted string — JSON-typed fields must not pass through Python's permissive int() where JS === rejects | verify → |
fail-unreferenced-junk-proof | must FAIL | a proof entry referencing nothing and reaching nothing — every proofs entry must verify; unexplained material is a lie, not decoration | verify → |
fail-wrong-pin | must FAIL under --key pin | pinning an unrelated key must not bless the pack — the browser has no pin flag, so watch it VERIFY self-declared: that green stamp is exactly the attack a pin defeats (attest verify pack.zip --key reproduces the FAIL) | verify → |
Back to the landing page ·
the oracle as JSON · regenerate:
tools/make_vectors.py (never hand-edit the zips).