code wiki / (root) / nx_mse_handshake.nx

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}