nx_connect_e2e_proof.nx source
↩ module page · 79 lines · 2972 B
1// nx_connect_e2e_proof.nx -- LIVE-LOOP witness for the full-E2E CONNECT proof: computes the EXACT bytes
2// the browser client produces (the wasm mcw_* API is a thin wrapper over these same native mc_* functions,
3// and the wasm is separately proven bit-exact vs RFC 8439 in nx_media_crypt_wasm_gate). Used to drive the
4// two-user proof over the PUBLIC edge: seal as Alice -> POST -> fetch as Bob -> open -> plaintext must
5// round-trip. license_tier: ORIGINAL
6// nx_connect_e2e_proof seal <keyhex64> <seq> <plaintext> -> ciphertext hex on stdout
7// nx_connect_e2e_proof open <keyhex64> <seq> <cthex> -> plaintext on stdout
8import "nx_syscalls.nx"
9import "nx_media_crypt.nx"
10
11const EP_MAX: i64 = 4096
12
13func ep_w(s: *u8, n: i64) -> i64 { sys_write(1, s, n); return 0 }
14func ep_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
15func ep_seq(a: *u8, b: *u8) -> i64 {
16 var i: i64=0
17 while a[i]!=(0 as u8) { if a[i]!=b[i] { return 0 } i=i+1 }
18 if b[i]!=(0 as u8) { return 0 }
19 return 1
20}
21func ep_atoi(s: *u8) -> i64 {
22 var v: i64=0
23 var i: i64=0
24 while s[i]!=(0 as u8) {
25 let c: i64 = s[i] as i64
26 if c>=48 { if c<=57 { v=v*10+(c-48) } }
27 i=i+1
28 }
29 return v
30}
31
32func main(argc: i64, argv: *i64) -> i64 {
33 if argc < 5 { sys_write(2, "usage: nx_connect_e2e_proof seal|open <keyhex64> <seq> <text|cthex>\n" as *u8, 68); return 2 }
34 let mode: *u8 = argv[1] as *u8
35 let keyhex: *u8 = argv[2] as *u8
36 let seqs: *u8 = argv[3] as *u8
37 let data: *u8 = argv[4] as *u8
38 if ep_slen(keyhex)!=64 { sys_write(2, "key must be 64 hex chars\n" as *u8, 25); return 2 }
39 let key: *u8 = sys_mmap(32)
40 mc_key(keyhex, 64, key)
41 let nonce: *u8 = sys_mmap(12)
42 mc_nonce("connect1" as *u8, ep_atoi(seqs), nonce)
43 let buf: *u8 = sys_mmap(EP_MAX)
44 let scratch: *u8 = sys_mmap(EP_MAX)
45 if ep_seq(mode, "seal" as *u8)==1 {
46 let n: i64 = ep_slen(data)
47 var i: i64=0
48 while i<n { buf[i]=data[i]; i=i+1 }
49 mc_xform(key, nonce, 0, buf, n, scratch)
50 let hexout: *u8 = sys_mmap(EP_MAX*2)
51 i=0
52 while i<n {
53 let b: i64 = buf[i] as i64
54 var hi: i64 = (b>>4)&0xf
55 var lo: i64 = b&0xf
56 if hi<10 { hexout[i*2]=(48+hi) as u8 } else { hexout[i*2]=(87+hi) as u8 }
57 if lo<10 { hexout[i*2+1]=(48+lo) as u8 } else { hexout[i*2+1]=(87+lo) as u8 }
58 i=i+1
59 }
60 ep_w(hexout, n*2)
61 ep_w("\n" as *u8, 1)
62 return 0
63 }
64 if ep_seq(mode, "open" as *u8)==1 {
65 let hn: i64 = ep_slen(data)
66 let n: i64 = hn/2
67 var i: i64=0
68 while i<n {
69 buf[i]=((mc_hexval(data[i*2] as i64)<<4)|mc_hexval(data[i*2+1] as i64)) as u8
70 i=i+1
71 }
72 mc_xform(key, nonce, 0, buf, n, scratch)
73 ep_w(buf, n)
74 ep_w("\n" as *u8, 1)
75 return 0
76 }
77 sys_write(2, "unknown mode\n" as *u8, 13)
78 return 2
79}