Spec: CapGlyph/capglyph-spec 1.0.0 · Core: capglyph-core 0.1.0
Vectors: 1024 fixtures · Harness: capglyph conformance test (Rust, in CapGlyph/capglyph-cli) and scripts/conformance.py (Python, standalone)
Cross-language conformance suite for capglyph-core framing, ECC, carrier lattice, and policy. SDKs claiming CapGlyph v1 compliance MUST pass valid/ and must fail each other category with the documented error code.
.
├── README.md # this file
├── manifest.json # index of all vectors (1024 entries, SHA-256 per file)
├── vectors/
│ ├── valid/ # 256 — crypto+policy pass (CBOR/HMAC/ECC roundtrip)
│ ├── invalid/ # 128 — structural invalid (unknown payload_type, bad CBOR)
│ ├── malformed/ # 128 — truncated / length-mismatch / short tag
│ ├── tampered/ # 256 — flipped bit/byte → AUTH_FAILED or TAMPERED
│ ├── expired/ # 128 — crypto valid, policy EXPIRED (mock not_before/expires_at)
│ └── revoked/ # 128 — crypto valid, policy REVOKED (mock_revoked_at)
├── images/ # sample covers (PNG, 512×512) — not counted in 1024
│ ├── cover_512_checker.png
│ ├── cover_512_gradient.png
│ └── README.md
├── scripts/
│ ├── generate.py # deterministic generator (1024 vectors + manifest + images)
│ └── README.md
└── tools/
└── conformance.py # Python harness (validates without cargo)
Each vector is a JSON file, e.g. vectors/valid/valid-0001.json:
{
"id": "valid-0001",
"category": "valid",
"spec_version": "1.0.0",
"protocol_version": 1,
"payload_type": "Credential",
"payload_type_id": 1,
"flags": 0,
"payload_hex": "000102030405060708090a0b0c0d0e0f",
"payload_len": 16,
"k_mac_hex": "4242424242424242424242424242424242424242424242424242424242424242",
"cbor_frame_hex": "850101001050000102030405060708090a0b0c0d0e0f",
"tag_hex": "…32 bytes HMAC-SHA256(CborFrame, K_mac)",
"sealed_hex": "cbor_frame || tag",
"expected_success": true,
"expected_code": null,
"expected_error": null,
"description": "valid credential roundtrip 16B opaque token",
"carrier": "dct",
"ecc_profile": "Repetition8",
"threshold": 4.0,
"mock_policy": null
}| Category | Count | expected_success |
expected_code |
What is checked |
|---|---|---|---|---|
valid |
256 | true |
null |
seal → byte-identical sealed_hex, then open(sealed, K_mac) → payload_hex, CBOR payload_len matches |
invalid |
128 | false |
E_MALFORMED_FRAME or E_VERSION_UNSUPPORTED |
unknown PayloadType, zero-length sealed, wrong array length |
malformed |
128 | false |
E_MALFORMED_FRAME |
truncated CBOR, payload_len ≠ actual, short tag (<32 B) |
tampered |
256 | false |
E_AUTH_FAILED or E_TAMPERED |
1-byte flip in CborFrame or tag |
expired |
128 | false |
E_EXPIRED |
crypto pass, but mock_policy.expires_at in the past |
revoked |
128 | false |
E_REVOKED |
crypto pass, but mock_policy.revoked_at set |
tampered that flips a non-tag byte MUST be E_AUTH_FAILED (HMAC fail takes precedence over E_TAMPERED per spec.md §8 precedence). malformed that destroys CBOR structure MUST be E_MALFORMED_FRAME, not E_AUTH_FAILED.
From the isolated monorepo:
# from capglyph-cli
cargo run -- conformance test --vectors ../capglyph-test-vectors/vectors
# or after install
capglyph conformance test --vectors ../capglyph-test-vectors/vectors --verboseFrom anywhere with capglyph-core in path:
python3 ../capglyph-test-vectors/tools/conformance.py --vectors vectors --verbosepython3 scripts/conformance.py --vectors vectors
python3 tools/conformance.py --vectors vectors --json-report report.jsonBoth harnesses exit 0 on full conformance, 1 on any failure, and print a per-category summary:
valid: 256/256 pass ✓
invalid: 128/128 pass ✓
malformed: 128/128 pass ✓
tampered: 256/256 pass ✓
expired: 128/128 pass ✓
revoked: 128/128 pass ✓
total: 1024/1024 vectors passed — conformance ✓
python3 scripts/generate.py --count 1024 --seed 41
# deterministic — same seed → byte-identical vectors, manifest, and images
python3 scripts/generate.py --count 1024 --seed 41 --out vectors --images imagesGenerator uses only stdlib (hashlib, hmac, zlib, struct). CBOR is deterministic per spec.md §3.1 (shortest-int, definite array 0x85, serde_bytes bstr). No cbor2 dependency — the encoder is inlined and matches ciborium 0.2 (see scripts/README.md for the equivalence proof with 85 01 01 … hex snapshots).
Vectors are snapshots, not live. To add coverage (e.g. for Ed25519 v2 or DWT ±256/±32 lattice), extend scripts/generate.py's profile table and re-run with an incremented spec_version. Never hand-edit sealed_hex without re-deriving tag_hex.
Apache-2.0 — same as CapGlyph/capglyph-spec and CapGlyph/capglyph-core.