4.1 KiB
live-conformance/e2ee — end-to-end encrypted rooms
The corpus of 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 byjoule_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:acceptwith itssuite, 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_keyandmoq_salt(§4.2, §4.5, §5.7), in both suites and at the KID's limits;objects: sealed objects. A sealed one states itsinput(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), everyderivedvalue (track base key, KID, Full Track Name, key, salt, Immutable Properties, plaintext, AAD, nonce), theobjectas a -22 object carries it (its property list and sealed payload, hexadecimal), and itscontent_hash, the BLAKE3 hash a receipt commits to. The negatives are controls of one defect each. Each is opened by the receiver itscontextnames and has itsoutcome:openedwith the BLAKE3 hash of its original payload, or a reason of §6;rooms: transcripts, each a list ofsteps(a lifecycleevent, the group'screate, aproposal, acommitwith its sender's leaf, the indexes of the epoch's proposals it holds and the new epoch's application secret, or anobjectwith itsdeliveries), and the outcome a replay gives it (§5.4 to §5.6, §6):acceptorrefusewith 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-01Appendix 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.