nx_mse_handshake.nx source
↩ module page · 130 lines · 10742 B
1// nx_mse_handshake.nx -- the FULL MSE/PE obfuscated handshake over a real socket (anti-throttle keystone).
2//
3// Two parties complete the Message Stream Encryption handshake so an ISP's DPI sees only high-entropy bytes
4// (no "BitTorrent protocol" string, no fixed structure) and can't fingerprint+throttle the connection:
5// A->B: Ya (DH pubkey; + optional PadA -- 0 here)
6// B->A: Yb
7// A->B: HASH(req1,S) | HASH(req2,SKEY)^HASH(req3,S) | RC4_keyA( VC | crypto_provide | lenPadC=0 | lenIA=0 )
8// B->A: RC4_keyB( VC | crypto_select | lenPadD=0 )
9// then: the RC4 streams (keyA A->B, keyB B->A) carry the rest -- e.g. the BT handshake -- ENCRYPTED.
10// Composes nx_mse_keys (DH + keyA/keyB + req-hashes) + nx_rc4 + sockets. GATE = loopback A<->B: negotiate RC4,
11// verify VC both ways, then A sends an ENCRYPTED payload B decrypts to the exact plaintext. (Pads=0 for the
12// gate; live interop adds random pads + B's req1-hash stream-sync scan -- noted, not needed to prove the crypto.)
13//
14// nx_mse_handshake -- no-arg = the loopback GATE
15// license_tier: ORIGINAL module: nishi-core.torrent.mse_handshake depends: mse_keys (dh+rc4+sha1)
16import "nx_mse_keys.nx"
17import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host
18const HS_MAGIC_1024: i64 = 1024
19
20const HS_PORT: i64 = 53811
21
22func hs_sockaddr(sa: *u8, port: i64, a: i64, b: i64, c: i64, d: i64) -> i64 {
23 sa[0]=2 as u8; sa[1]=0 as u8; sa[2]=((port>>8)&0xff) as u8; sa[3]=(port&0xff) as u8
24 sa[4]=a as u8; sa[5]=b as u8; sa[6]=c as u8; sa[7]=d as u8
25 var i: i64=8; while i<16 { sa[i]=0 as u8; i=i+1 } return 16
26}
27func hs_read_n(fd: i64, buf: *u8, n: i64) -> i64 { var g: i64=0; while g<n { let r: i64=sys_read(fd, buf+g, n-g); if r<=0 { return 0-1 } g=g+r } return g }
28func hs_write_n(fd: i64, buf: *u8, n: i64) -> i64 { var o: i64=0; while o<n { let w: i64=sys_write(fd, buf+o, n-o); if w<=0 { return 0-1 } o=o+w } return n }
29func if_zero(v: i64) -> i64 { if v==0 { return 1 } return 0 }
30func hs_put4(b: *u8, o: i64, v: i64) -> i64 { b[o]=((v>>24)&0xff) as u8; b[o+1]=((v>>16)&0xff) as u8; b[o+2]=((v>>8)&0xff) as u8; b[o+3]=(v&0xff) as u8; return o+4 }
31func hs_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 }
32func hs_xor20(a: *u8, b: *u8, out: *u8) -> i64 { var i: i64=0; while i<20 { out[i]=((a[i] as i64) ^ (b[i] as i64)) as u8; i=i+1 } return 0 }
33// init an RC4 channel: KSA(key20) + discard 1024 (MSE mandate). S_box=256, ij={0,0}.
34func hs_rc4_open(S: *u8, ij: *i64, key20: *u8) -> i64 { rc4_ksa(S, key20, 20); ij[0]=0; ij[1]=0; rc4_skip(S, ij, HS_MAGIC_1024); return 0 }
35
36func main() -> i64 {
37 md_p("MSE-HANDSHAKE-GATE authored=organ (full obfuscated handshake over a socket)\n" as *u8)
38 let p: *i64 = sys_mmap((MSE_N+2)*8) as *i64; md_load_p(p)
39 // SKEY = the torrent info_hash both peers know (B identifies it via req2^req3)
40 let skey: *u8 = sys_mmap(24); var i: i64=0; while i<20 { skey[i]=(0x40+i) as u8; i=i+1 }
41 let VCZ: *u8 = sys_mmap(8); i=0; while i<8 { VCZ[i]=0 as u8; i=i+1 }
42 let PAYLOAD: *u8 = "MSE-OVER-DPI-OK!" as *u8 // 16-byte post-handshake encrypted test payload
43 let sa: *u8 = sys_mmap(16); hs_sockaddr(sa, HS_PORT, 127,0,0,1)
44 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
45 var bound: i64=0
46 if lfd>=0 { let one: *u8=sys_mmap(4); one[0]=1 as u8; one[1]=0 as u8; one[2]=0 as u8; one[3]=0 as u8; sys_setsockopt(lfd, SOL_SOCKET, 2, one, 4); sys_set_socket_timeout(lfd, 5); if sys_bind(lfd, sa, 16)>=0 { if sys_listen(lfd, 4)>=0 { bound=1 } } }
47 if bound==0 { md_p("MSE-HANDSHAKE-GATE bound=0 verdict=RED\n" as *u8); sys_exit(1); return 1 }
48
49 let pid: i64 = sys_fork()
50 if pid == 0 {
51 // ===== RECEIVER B =====
52 let afd: i64 = sys_accept(lfd); if afd<0 { sys_exit(1); return 1 }
53 sys_set_socket_timeout(afd, 5)
54 let xb: *i64 = sys_mmap((MSE_N+2)*8) as *i64; bi_zero(xb, MSE_N); xb[0]=0x7fedcba; xb[1]=0x0987654; xb[2]=0x3210fed
55 let ya: *i64 = sys_mmap((MSE_N+2)*8) as *i64; let yb: *i64 = sys_mmap((MSE_N+2)*8) as *i64; let s: *i64 = sys_mmap((MSE_N+2)*8) as *i64
56 let yab: *u8 = sys_mmap(128)
57 if hs_read_n(afd, yab, 96) != 96 { sys_exit(1); return 1 } // recv Ya
58 bi_from_bytes_be(ya, MSE_N, yab, 96)
59 mse_dh_public(xb, p, yb); let ybb: *u8 = sys_mmap(128); bi_to_bytes_be(ybb, 96, yb, MSE_N); hs_write_n(afd, ybb, 96) // send Yb
60 mse_dh_shared(ya, xb, p, s); let sbytes: *u8 = sys_mmap(128); bi_to_bytes_be(sbytes, 96, s, MSE_N)
61 let keyA: *u8 = sys_mmap(24); let keyB: *u8 = sys_mmap(24); mk_derive("keyA" as *u8, sbytes, skey, keyA); mk_derive("keyB" as *u8, sbytes, skey, keyB)
62 // recv stage3: req1(20) | xor(20) | RC4_keyA(16)
63 let st3: *u8 = sys_mmap(64); if hs_read_n(afd, st3, 56) != 56 { sys_exit(1); return 1 }
64 let e_req1: *u8 = sys_mmap(24); mk_hash_pref("req1" as *u8, sbytes, 96, e_req1)
65 var ok_req1: i64=0; if hs_memeq(st3, e_req1, 20)==1 { ok_req1=1 }
66 let h2: *u8 = sys_mmap(24); let h3: *u8 = sys_mmap(24); mk_hash_pref("req2" as *u8, skey, 20, h2); mk_hash_pref("req3" as *u8, sbytes, 96, h3)
67 let e_xor: *u8 = sys_mmap(24); hs_xor20(h2, h3, e_xor)
68 var ok_xor: i64=0; if hs_memeq((st3 as i64 + 20) as *u8, e_xor, 20)==1 { ok_xor=1 } // identifies SKEY
69 let SBd: *u8 = sys_mmap(256); let ijBd: *i64 = sys_mmap(16) as *i64; hs_rc4_open(SBd, ijBd, keyA) // B decrypts A's stream (keyA)
70 let dec3: *u8 = sys_mmap(24); var c: i64=0; while c<16 { dec3[c]=st3[40+c]; c=c+1 } rc4_crypt(SBd, ijBd, dec3, 16) // enc block at [40]: after req1(20)+xor(20)
71 var ok_vc_a: i64=0; if hs_memeq(dec3, VCZ, 8)==1 { ok_vc_a=1 } // A's VC decrypts to zeros
72 let provide: i64 = ((dec3[8] as i64)<<24)|((dec3[9] as i64)<<16)|((dec3[10] as i64)<<8)|(dec3[11] as i64)
73 var ok_provide: i64=0; if (provide & 2) != 0 { ok_provide=1 } // A offered RC4
74 // send stage5: RC4_keyB( VC(8) | crypto_select=2 (4) | lenPadD=0 (2) ) = 14 bytes
75 let SBe: *u8 = sys_mmap(256); let ijBe: *i64 = sys_mmap(16) as *i64; hs_rc4_open(SBe, ijBe, keyB) // B encrypts to A (keyB)
76 let p5: *u8 = sys_mmap(24); var o5: i64=0; c=0; while c<8 { p5[o5]=0 as u8; o5=o5+1; c=c+1 } o5=hs_put4(p5, o5, 2); p5[o5]=0 as u8; p5[o5+1]=0 as u8; o5=o5+2
77 rc4_crypt(SBe, ijBe, p5, 14); hs_write_n(afd, p5, 14)
78 // recv A's post-handshake ENCRYPTED payload (16), decrypt with the SAME keyA stream (continues)
79 let ed: *u8 = sys_mmap(32); if hs_read_n(afd, ed, 16) != 16 { sys_exit(1); return 1 }
80 rc4_crypt(SBd, ijBd, ed, 16)
81 var ok_payload: i64=0; if hs_memeq(ed, PAYLOAD, 16)==1 { ok_payload=1 }
82 sys_close(afd)
83 var ball: i64=0
84 if ok_req1==1 { if ok_xor==1 { if ok_vc_a==1 { if ok_provide==1 { if ok_payload==1 { ball=1 } } } } }
85 if ball==1 { sys_exit(0); return 0 }
86 sys_exit(1); return 1
87 }
88
89 // ===== INITIATOR A =====
90 let cfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0); sys_set_socket_timeout(cfd, 5)
91 var conn: i64=0; if nx_connect_bounded(cfd, sa, 16, NX_CONN_DEFAULT_MS)>=0 { conn=1 }
92 var a_vc_ok: i64=0; var a_select_ok: i64=0
93 if conn==1 {
94 let xa: *i64 = sys_mmap((MSE_N+2)*8) as *i64; bi_zero(xa, MSE_N); xa[0]=0x1234567; xa[1]=0x89abcde; xa[2]=0xf011223
95 let ya: *i64 = sys_mmap((MSE_N+2)*8) as *i64; let yb: *i64 = sys_mmap((MSE_N+2)*8) as *i64; let s: *i64 = sys_mmap((MSE_N+2)*8) as *i64
96 mse_dh_public(xa, p, ya); let yab: *u8 = sys_mmap(128); bi_to_bytes_be(yab, 96, ya, MSE_N); hs_write_n(cfd, yab, 96) // send Ya
97 let ybb: *u8 = sys_mmap(128); if hs_read_n(cfd, ybb, 96)==96 {
98 bi_from_bytes_be(yb, MSE_N, ybb, 96); mse_dh_shared(yb, xa, p, s)
99 let sbytes: *u8 = sys_mmap(128); bi_to_bytes_be(sbytes, 96, s, MSE_N)
100 let keyA: *u8 = sys_mmap(24); let keyB: *u8 = sys_mmap(24); mk_derive("keyA" as *u8, sbytes, skey, keyA); mk_derive("keyB" as *u8, sbytes, skey, keyB)
101 // stage3: req1 | (req2^req3) | RC4_keyA( VC(8) | crypto_provide=2 (4) | lenPadC=0 (2) | lenIA=0 (2) )
102 let h1: *u8 = sys_mmap(24); mk_hash_pref("req1" as *u8, sbytes, 96, h1)
103 let h2: *u8 = sys_mmap(24); let h3: *u8 = sys_mmap(24); mk_hash_pref("req2" as *u8, skey, 20, h2); mk_hash_pref("req3" as *u8, sbytes, 96, h3)
104 let xr: *u8 = sys_mmap(24); hs_xor20(h2, h3, xr)
105 let SAe: *u8 = sys_mmap(256); let ijAe: *i64 = sys_mmap(16) as *i64; hs_rc4_open(SAe, ijAe, keyA) // A encrypts (keyA)
106 let p3: *u8 = sys_mmap(24); var o3: i64=0; var c: i64=0; while c<8 { p3[o3]=0 as u8; o3=o3+1; c=c+1 } o3=hs_put4(p3, o3, 2); p3[o3]=0 as u8; p3[o3+1]=0 as u8; o3=o3+2; p3[o3]=0 as u8; p3[o3+1]=0 as u8; o3=o3+2
107 rc4_crypt(SAe, ijAe, p3, 16)
108 let st3: *u8 = sys_mmap(64); c=0; while c<20 { st3[c]=h1[c]; c=c+1 } c=0; while c<20 { st3[20+c]=xr[c]; c=c+1 } c=0; while c<16 { st3[40+c]=p3[c]; c=c+1 }
109 hs_write_n(cfd, st3, 56)
110 // recv stage5: RC4_keyB( VC(8) | crypto_select(4) | lenPadD(2) ) = 14
111 let SAd: *u8 = sys_mmap(256); let ijAd: *i64 = sys_mmap(16) as *i64; hs_rc4_open(SAd, ijAd, keyB) // A decrypts (keyB)
112 let r5: *u8 = sys_mmap(24); if hs_read_n(cfd, r5, 14)==14 {
113 rc4_crypt(SAd, ijAd, r5, 14)
114 if hs_memeq(r5, VCZ, 8)==1 { a_vc_ok=1 }
115 let sel: i64 = ((r5[8] as i64)<<24)|((r5[9] as i64)<<16)|((r5[10] as i64)<<8)|(r5[11] as i64)
116 if sel==2 { a_select_ok=1 }
117 // post-handshake: send an ENCRYPTED payload on the SAME keyA stream (continues)
118 let ed: *u8 = sys_mmap(32); c=0; while c<16 { ed[c]=PAYLOAD[c]; c=c+1 } rc4_crypt(SAe, ijAe, ed, 16); hs_write_n(cfd, ed, 16)
119 }
120 }
121 }
122 let st: *i64 = sys_mmap(16) as *i64; sys_wait4(pid, st, 0); sys_close(cfd); sys_close(lfd)
123 let child_ok: i64 = ((st[0]>>8)&0xff) // 0 = B verified everything
124 md_p(" A: conn=" as *u8); md_p(if_s(conn)); md_p(" VC_from_B_ok=" as *u8); md_p(if_s(a_vc_ok)); md_p(" crypto_select=RC4=" as *u8); md_p(if_s(a_select_ok))
125 md_p(" | B(child) all-checks(req1+SKEY+VC+provide+decrypted-payload)=" as *u8); md_p(if_s(if_zero(child_ok))); md_p("\n" as *u8)
126 var allok: i64=0
127 if conn==1 { if a_vc_ok==1 { if a_select_ok==1 { if child_ok==0 { allok=1 } } } }
128 if allok==1 { md_p("MSE-HANDSHAKE-GATE verdict=GREEN (full obfuscated handshake -> RC4-encrypted stream, both sides verified)\n" as *u8); sys_exit(0); return 0 }
129 md_p("MSE-HANDSHAKE-GATE verdict=RED\n" as *u8); sys_exit(1); return 1
130}