Test vectors
The 436 vectors are the executable form of the specification. An independent implementation is conformant when it reproduces every byte of the generation vectors (identity, signing, encryption, attestation) and returns the expected accept or reject, step and error code for all the others. Where the text and a vector disagree, the vector wins and the text is amended.
Format
Each vector is three files with one base name: name.cbor (the exact bytes), name.json (a debug view) and name.expected.json (inputs, the verifier policy, and the required result). All keys come from fixed seeds written in plain hex, and the reference time is now = 1800000000.
Categories
28 categories: identity, signing, encryption, verify-positive, verify-negative, attestation, chain-positive, chain-negative, srl, srl-context, log, log-admission, monitor, atep-r-positive, atep-r-negative, retired and successor (positive and negative), and the anchoring and discovery categories (checkpoint-hash, anchor-record, chain-id, anchor-envelope, anchor-media-type, require-anchor, anchor-not-supported, registry-endpoint, domain-binding).
Who passes
The Rust core, the JavaScript package (the same Rust compiled to WebAssembly) and the independent Python implementation pass the vectors that apply to them: the Rust core passes all 436, and the JavaScript and Python implementations pass 431 and skip by name the five for a log (four) and a monitor (one), which the Rust log and monitor pass. The Python implementation was written from the specification and the vectors only and produced 44 reports of ambiguity in the text; all are resolved in the specification (see the implementation findings in the repository).
Not covered
Hedged ML-DSA signing inputs and some edge cases are in the known gaps table of specification section 12. An implementation outside the project does not exist yet; that is the most useful next contribution.