open-standards/wai/live-conformance/e2ee/README.md
2026-10-19 20:54:09 -04:00

70 lines
4.1 KiB
Markdown

# live-conformance/e2ee — end-to-end encrypted rooms
The corpus of [`extensions/confidentiality.md`](../../extensions/confidentiality.md) §14:
rooms whose media objects are sealed as MoQ secure objects under keys from one MLS group per
room.
## Files
- `vectors.json`, written by `joule_moq_e2ee_vectors gen`:
- `records`: confidentiality records (`WRE1`, §3), each with the room id, the authority's
key and the descriptor's recording mode it is checked against, and its outcome: `accept`
with its `suite`, or the reason of §3.3;
- `key_schedule`: for an epoch's application secret, a sender's leaf and a track, the
track base key, the KID, the Serialized Full Track Name, `moq_key` and `moq_salt`
(§4.2, §4.5, §5.7), in both suites and at the KID's limits;
- `objects`: sealed objects. A sealed one states its `input` (the application secret,
epoch, leaf, track, Group ID, Object ID, priority, payload, whether it carries an inner
digest, padding, other encrypted entries, other Immutable Properties), every `derived`
value (track base key, KID, Full Track Name, key, salt, Immutable Properties, plaintext,
AAD, nonce), the `object` as a -22 object carries it (its property list and sealed
payload, hexadecimal), and its `content_hash`, the BLAKE3 hash a receipt commits to. The
negatives are controls of one defect each. Each is opened by the receiver its `context`
names and has its `outcome`: `opened` with the BLAKE3 hash of its original payload, or a
reason of §6;
- `rooms`: transcripts, each a list of `steps` (a lifecycle `event`, the group's `create`,
a `proposal`, a `commit` with its sender's leaf, the indexes of the epoch's proposals it
holds and the new epoch's application secret, or an `object` with its `deliveries`), and
the outcome a replay gives it (§5.4 to §5.6, §6): `accept` or `refuse` with the reason and
the step, each epoch's roster, and each delivery's outcome;
- `codes`: the reasons of §13, in its order.
- `rfc9605.json`: RFC 9605 Appendix C, its header, AES-CTR with HMAC, and SFrame encryption
vectors.
- `secure-objects-01.json`: `draft-ietf-moq-secure-objects-01` Appendix B, its Full Track
Name, key derivation, nonce and AAD, and encryption vectors.
**Equivalence.** A conforming implementation gives every record, object and delivery its
outcome, every room its outcome, rosters and deliveries, and every key schedule entry and
derived value the bytes stated; it reproduces RFC 9605's vectors, and secure objects' exactly
in suites `0x0004` and `0x0005`, with the difference §11.2 states in `0x0001` and `0x0002`.
**The boundary.** Each epoch's application secret is given, standing for
`MLS-Exporter("wai live e2ee", room_id, 32)` (§5.7); everything after it is checked. That a
real MLS group exports them, and that its rosters are the replay's, is checked by
`joule-moq-mls`'s tests, which run the groups.
**Provenance.** Generated here: `joule_moq_e2ee_vectors gen` writes `vectors.json` from rooms
authored in code, from fixed seeds: every key is an Ed25519 key whose seed is SHA-256 of
`wai:e2ee/corpus/key`, a zero byte and a label; every application secret SHA-256 of
`wai:e2ee/corpus/secret`, a zero byte, the room's label, the generation and the epoch; every
payload SHA-256 in counter mode over `wai:e2ee/corpus/bytes` and a label; the room id SHA-256
of `wai:e2ee/corpus/room` and a label. AES-GCM and Ed25519 signing are deterministic, so the
file is the same bytes on every machine. No recorded data. `rfc9605.json` and
`secure-objects-01.json` are the test vectors those documents print, copied with the
whitespace inside each value removed and each document's numbers as JSON numbers; nothing in
them is generated here.
## Checking
```
cd joule-code/joule-code-rs
cargo run -p joule-moq-mls --bin joule_moq_e2ee_vectors verify ../../wai/live-conformance/e2ee
cargo test -p joule-moq --features secure-objects
cargo test -p joule-moq-mls
cd wai
python3 -I live-conformance/e2ee_verify.py live-conformance/e2ee
```
`e2ee_verify.py` is the second implementation, written from the text with the standard
library alone; it writes AES and GCM itself, for these vectors only.