Protocol test vectors
KM43 / reproducible bytes
One machine-readable answer for every key derivation, MAC preimage, encoding boundary, and complete frame an implementation must reproduce.
- Artifact
v1.json- Generated by
cargo xtask vectors- Consumers
- Rust controller and browser client
- Editing rule
- Regenerate; never hand-edit
Why vectors exist
Section titled “Why vectors exist”A key-derivation disagreement is invisible on the wire. Two
implementations that parameterise HKDF differently produce frames that look
perfect in a hex dump and fail every MAC, and the only symptom is “it does not
work” on a bench day. A CRC is the same: CRC-16/CCITT-FALSE names one algorithm
but nobody remembers which of the CCITT variants that is at 11 p.m.
Both km43-proto and the browser client test against the same file, so each side
can prove itself alone before the two halves are ever connected.
cargo xtask vectorscargo xtask vectors validates every primitive against the RFC’s own published
vectors before computing any of ours, and refuses to write the file if one
fails:
| Primitive | Checked against |
|---|---|
| HKDF-SHA256 | RFC 5869 A.1 and A.3 |
| HMAC-SHA256 | RFC 4231 case 2 |
| CRC-16/CCITT-FALSE | catalogue check value 0x29B1 |
| COBS | Cheshire & Baker, all nine cases |
| CBOR | RFC 8949 Appendix A |
That ordering is the point. A vector file computed by an unvalidated implementation makes two implementations agree on the same bug, which is worse than having no vectors at all — the bug now has a test protecting it.
It has already earned its keep twice. Writing the COBS cases caught an encoder that appended a spurious trailing group, and in the paper’s case 9 — a run of exactly 254 bytes followed by a zero — that bug silently dropped the trailing zero byte. A round-trip test never sees it, because the decoder happily produces the shorter string.
What is in the file
Section titled “What is in the file”| Section | Contents |
|---|---|
conventions | Byte order, truncation, HKDF argument assignment, CBOR profile |
inputs | The fixed, obviously-fake secret, device id, challenge and nonce |
limits | MAX_PAYLOAD and the derivation of MAX_FRAME |
derived_keys | client_key and session_key with every HKDF argument spelled out |
macs | Pair proof, pair ack, Hello proof, signed request, response, event — each with its full preimage in hex |
crc16, cobs | Edge cases: empty, a single zero, embedded zeros, the 254-byte block boundary |
frame | One complete encoded frame, envelope through delimiter |
The inputs are deliberately unmistakable — printed_secret is 00 01 02 … 1f
and device_id spells ORIGIN89 DEMO 01 — so nobody can confuse a test vector
for a real device secret in a log.