live-conformance/watermark/vectors.json from wai_live_watermark_vectors, and live_watermark_verify.py, written from the extension's text, which agrees on every vector, fails every mutated copy and catches a verifier that leaves out any one of its checks. Co-Authored-By: Claude Opus 5.5 <[email protected]>
55 lines
3.8 KiB
Markdown
55 lines
3.8 KiB
Markdown
# live-conformance/watermark — forensic watermark sessions
|
|
|
|
The corpus of [`extensions/forensic-watermark.md`](../../extensions/forensic-watermark.md) §12,
|
|
in one file, `vectors.json`: three rooms, ETSI TS 104 002 watermark tokens, lists of `WWS1`
|
|
session records with or without their tokens, `WWQ1` recovered sequences matched against
|
|
records, and `WWD1` disclosures, each with the outcome the extension gives it.
|
|
|
|
- **`rooms`**: each room's `WRD1` descriptor, its `WRG1` grants, its key-log head (or `null`)
|
|
and its `WRE1` confidentiality record (or `null`), as hexadecimal; `broadcast` (an origin
|
|
whose key log lists two edges with `live/watermark`, a relay with `live/relay` alone and a
|
|
revoked edge; region pin `DE`, `FR`; retention 30 days), `keyless` (no origin; its clock is
|
|
its edge) and `e2ee` (end-to-end encrypted). A vector names its room and may carry a
|
|
`room_override`, whose members replace the room's.
|
|
- **`tokens`**: each token's bytes, read by §4.2: `read` with what it gives (§4.3: `cwt_tag`,
|
|
`alg`, `vendor`, `patlen`, `source`, the clear `pattern` or `null`, `iat`, `exp`, `nbf`), or
|
|
`refuse` with `token_malformed` or `token_unsupported`.
|
|
- **`sessions`**: a list of records, each `record` with its `token` or `null`, verified by
|
|
§9.1: `accept` with each record's facts (its `digest`, `edge`, `owner`, `media`, `kids`,
|
|
span, `vendor`, `source`, `patlen`, the number of positions `served`, `segments`,
|
|
`unmarked`, `region`, `expires`, and its `token`'s facts or `null`), or `refuse` with the
|
|
`reason` and the place `at`: `descriptor`, `key_log`, `grant` and its `index`,
|
|
`confidentiality`, or `session` and its `index`.
|
|
- **`matches`**: the records and a `sequence`, by §9.2: `matched` or `unmatched` (with
|
|
`no_match` or `ambiguous_match`), and the `match`: the sequence's digest, the positions it
|
|
`stated`, each `candidate` (its `index`, `digest`, whether it `agrees`, and its `first`
|
|
disagreement, a `position` and `unserved` or `differs`), and the matched `session` or
|
|
`null`; or `refuse` at `sequence` (or at a record).
|
|
- **`disclosures`**: one `record` with its `token`, a `sequence` and a `disclosure`, by §9.3:
|
|
`accept` with its `facts` (its `digest`, the `session`'s, the `sequence`'s, the `grant`, the
|
|
`principal`, the positions `stated`, and `token_given`), or `refuse` with the `reason` and
|
|
`at`.
|
|
|
|
A verifier that reaches another outcome, reason, place or fact does not conform.
|
|
|
|
**Provenance.** Generated here: `wai_live_watermark_vectors gen` writes `vectors.json` from
|
|
records authored in code, from fixed seeds. Every key is SHA-256 of a fixed label and an
|
|
index (`principals` lists them); every pattern, salt, KID and copy digest is SHA-256 of a label
|
|
and an index; every time is a constant (the rooms' `t0` is 2026-10-18T00:00:00Z); every origin
|
|
is an `.example` name (RFC 2606); and Ed25519 signing is deterministic (RFC 8032), so the file
|
|
is the same bytes on every machine. The tokens are COSE_Mac0 under HMAC 256/256 keyed by
|
|
`wmt_key`, which no verifier checks (§4.4); an encrypted pattern is a COSE_Encrypt0 or
|
|
COSE_Encrypt of the right shape whose bytes no verifier opens. Nothing here was recorded from
|
|
a deployment.
|
|
|
|
**Checks.** `wai_live_watermark_vectors verify` and `tests/live_watermark.rs` (wai-rs, feature
|
|
`live_watermark`) regenerate the file byte for byte and give every vector its outcome; the
|
|
generator asserts that every reason of §11 appears. `../live_watermark_verify.py` is the
|
|
second implementation, written from the extension's text: it shares no code with wai-rs, reads
|
|
rooms with `../live_rooms_verify.py`, reads tokens with a CBOR reader of its own, mutates
|
|
copies of the corpus and requires each to fail, and drops each of its own checks in turn and
|
|
requires the corpus to catch the weakened verifier.
|
|
|
|
```
|
|
python3 -I live_watermark_verify.py watermark
|
|
```
|