nx_sealed_sender.nx
buildroot/runtime/nx_sealed_sender.nx
about
nx_sealed_sender.nx -- C9 of the comms lane: SEALED SENDER (metadata privacy). Contract symbol
ss_seal == the /compare/comms C9 watch. REFEREE: nx_sealed_sender_gate.
DONE-RULE (comms.plan): the relay routes a message whose sender identity appears in no
relay-readable byte, proven by reading the relay's own capture in the gate.
SIGNAL'S FRONTIER, sovereign. A relay must be able to DELIVER a message without learning WHO sent
it. The envelope the relay sees carries only an opaque per-room ROUTING TOKEN (a keyed hash of the
room key -- reveals neither the room name nor its members) plus ciphertext and a MAC. The sender's
identity, the content, and the room name are ALL inside the E2EE payload. The recipient (who holds
the room key) opens it and learns the sender -- authenticated by an Ed25519 signature the relay
never sees, so within the group the sender is UNFORGEABLE, while to the relay it is INVISIBLE.
This is the full sealed-sender shape: a sender certificate (the Ed25519 pubkey) + a signature over
(routing_token || seq || plaintext), sealed inside the encrypted envelope.
HONEST METADATA SCOPE: the delivery SEQUENCE (seq) is relay-visible by design -- ordering is
delivery metadata, not sender identity, exactly as Signal's sealed sender still carries envelope
timing. What is provably ABSENT from every relay-readable byte is the SENDER, the CONTENT, and the
ROOM NAME. The gate proves that by scanning the envelope bytes.
PURE COMPOSITION, no new crypto: ed25519 (RFC 8032 sign/verify) + sha256 (HMAC/HKDF) + chacha20
(RFC 8439). No WebRTC, no OpenSSL. In production the room key is the C7 epoch secret, so sealed
sender rides the ratchet -- forward-secret and (with C8) post-quantum -- with no relay changes.
DEBT: the HMAC/HKDF/hex/file helpers are shared with C7 and C8; extraction to nx_kdf_lib is filed
(comms.plan kdf-lib-extract, now three consumers) -- named, not silently re-copied.
license_tier: ORIGINAL No hw writes (Rule 26).
dependencies 5 imports · 0 importers
imports: nx_syscalls.nxnx_itoa_lib.nxnx_sha256.nxnx_chacha20.nxnx_ed25519_signature.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 32 | const SMS_EXIT_OK: i64 = 0 |
| 33 | const SMS_EXIT_USAGE: i64 = 2 |
| 34 | const SMS_EXIT_REFUSED: i64 = 3 |
| 35 | const SMS_EXIT_CORRUPT: i64 = 5 |
| 36 | const SMS_KEY: i64 = 32 |
| 37 | const SMS_PUB: i64 = 32 |
| 38 | const SMS_SIG: i64 = 64 |
| 39 | const SMS_MAC: i64 = 32 |
| 40 | const SMS_NONCE: i64 = 12 |
| 41 | const SMS_ROUTE: i64 = 16 // routing-token bytes (128-bit opaque room handle) |
| 42 | const SMS_BLOCK: i64 = 64 |
| 43 | const SMS_IPAD: i64 = 54 |
| 44 | const SMS_OPAD: i64 = 92 |
| 45 | const SMS_NL: i64 = 10 |
| 46 | const SMS_PIPE: i64 = 124 |
| 47 | const SMS_FILECAP: i64 = 262144 |
| 48 | const SMS_HDR: i64 = 96 // sender_pub(32) || sig(64) inside the sealed payload |
functions
| 50 | func sms_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } |
| 51 | func sms_wn(s: *u8, n: i64) -> i64 { sys_write(1, s, n); return 0 } |
| 52 | func sms_num(v: i64) -> i64 { nxi_out(v); return 0 } |
| 53 | func sms_len(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } |
| 54 | func sms_eq(a: *u8, b: *u8) -> i64 called by 1: main |
| 60 | func sms_memeq(a: *u8, b: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { if a[i] != b[i] { return 0 } i = i + 1 } return 1 } called by 1: sms_open_verb |
| 61 | func sms_hexe(src: *u8, n: i64, dst: *u8) -> i64 |
| 74 | func sms_hexv(c: i64) -> i64 called by 1: sms_hexd |
| 80 | func sms_hexd(src: *u8, n: i64, dst: *u8) -> i64 |
| 93 | func sms_read(path: *u8, buf: *u8, cap: i64) -> i64 |
| 101 | func sms_writef(path: *u8, buf: *u8, n: i64) -> i64 |
| 110 | func sms_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64 = 0; while s[i] != (0 as u8) { d[o] = s[i]; o = o + 1; i = i + 1 } return o } |
| 111 | func sms_catn(d: *u8, o: i64, v: i64) -> i64 |
| 121 | func sms_field(line: *u8, n: i64, idx: i64, out: *u8) -> i64 |
| 134 | func sms_hmac(key: *u8, klen: i64, msg: *u8, mlen: i64, out: *u8) -> i64 |
| 162 | func sms_derive(secret: *u8, label: *u8, seq: i64, out: *u8) -> i64 |
| 176 | func sms_route(room_key: *u8, tok: *u8) -> i64 |
| 185 | func sms_transcript(tok: *u8, seq: i64, pt: *u8, ptlen: i64, out: *u8) -> i64 |
| 197 | func ss_seal(room_key: *u8, sender_priv: *u8, sender_pub: *u8, seq: i64, pt: *u8, ptlen: i64, out: *u8) -> i64 called by 1: sms_seal_verb calls 10: sys_mmapsms_routesms_transcripted25519_sign_fullsms_derivechacha20_encrypt+4 |
| 254 | func sms_keygen(priv_out: *u8, seed_hex: *u8) -> i64 |
| 275 | func sms_seal_verb(room_key_hex: *u8, priv_file: *u8, seq: i64, pt: *u8, env_out: *u8) -> i64 |
| 296 | func sms_route_verb(env_file: *u8) -> i64 |
| 312 | func sms_open_verb(room_key_hex: *u8, env_file: *u8) -> i64 |
| 386 | func sms_usage() -> i64 |
| 390 | func main(argc: i64, argv: *i64) -> i64 |