code wiki / (root) / nx_mse_dh.nx

nx_mse_dh.nx source

↩ module page · 77 lines · 5016 B

1// nx_mse_dh.nx -- MSE/PE Diffie-Hellman key exchange (BitTorrent Message Stream Encryption anti-throttle). 2// 3// MSE hides the BitTorrent handshake from ISP DPI so it can't be fingerprinted + throttled. Step 1 is a DH 4// exchange over a FIXED 768-bit prime P (the MSE/PE spec's prime) with generator G=2: each side picks a private 5// Xa, sends Ya = G^Xa mod P; the shared secret S = Yb^Xa mod P = Ya^Xb mod P feeds the RC4 handshake keys. 6// Composes bi_modexp (nx_bigint_modexp). P is 24 u32 limbs (768 bits). PUBLIC params -> no secrecy in P/G. 7// 8// nx_mse_dh -- no-arg = GATE: two parties derive the SAME S (Sa==Sb), pubkeys differ, S != 0. 9// license_tier: ORIGINAL module: nishi-core.torrent.mse_dh depends: nishi-core.crypto.bigint_modexp 10import "nx_bigint_modexp.nx" 11 12const MSE_N: i64 = 24 // 768-bit / 32 = 24 limbs 13// MSE/PE prime (768-bit, big-endian hex). G = 2. 14const MSE_P_HEX: *u8 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563" as *u8 15 16func if_s(b: i64) -> *u8 { if b==1 { return "1" as *u8 } return "0" as *u8 } 17func md_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 18func md_hv(c: i64) -> i64 { if c>=48 { if c<=57 { return c-48 } } if c>=97 { if c<=102 { return c-87 } } if c>=65 { if c<=70 { return c-55 } } return 0 } 19// decode `nbytes` of big-endian hex (2 chars/byte) into out. 20func md_hex2bytes(hex: *u8, nbytes: i64, out: *u8) -> i64 { 21 var i: i64=0; while i<nbytes { out[i] = ((md_hv(hex[i*2] as i64)*16)+md_hv(hex[i*2+1] as i64)) as u8; i=i+1 } return 0 22} 23 24// load the MSE prime P into an MSE_N-limb bignum 25func md_load_p(p: *i64) -> i64 { 26 let pb: *u8 = sys_mmap(128); md_hex2bytes(MSE_P_HEX, 96, pb) // 96 bytes = 768 bits 27 bi_from_bytes_be(p, MSE_N, pb, 96) 28 return 0 29} 30 31// nonzero? (n limbs) 32func md_nonzero(a: *i64, n: i64) -> i64 { var i: i64=0; while i<n { if (a[i] & 0xFFFFFFFF) != 0 { return 1 } i=i+1 } return 0 } 33func md_eq(a: *i64, b: *i64, n: i64) -> i64 { var i: i64=0; while i<n { if (a[i]&0xFFFFFFFF) != (b[i]&0xFFFFFFFF) { return 0 } i=i+1 } return 1 } 34 35// public key Y = G^X mod P (G=2). g,x,p,out all MSE_N limbs. 36func mse_dh_public(x: *i64, p: *i64, out: *i64) -> i64 { 37 let g: *i64 = sys_mmap((MSE_N+2)*8) as *i64; bi_zero(g, MSE_N); g[0]=2 38 bi_modexp(out, g, x, p, MSE_N) 39 return 0 40} 41// shared secret S = peer_pub^X mod P. 42func mse_dh_shared(peer_pub: *i64, x: *i64, p: *i64, out: *i64) -> i64 { 43 bi_modexp(out, peer_pub, x, p, MSE_N) 44 return 0 45} 46 47func main() -> i64 { 48 let p: *i64 = sys_mmap((MSE_N+2)*8) as *i64; md_load_p(p) 49 // two distinct private keys (deterministic for the gate; live uses a CSPRNG). ~128-bit each. 50 let xa: *i64 = sys_mmap((MSE_N+2)*8) as *i64; bi_zero(xa, MSE_N) 51 xa[0]=0x1234567; xa[1]=0x89abcde; xa[2]=0xf011223; xa[3]=0x3445566 52 let xb: *i64 = sys_mmap((MSE_N+2)*8) as *i64; bi_zero(xb, MSE_N) 53 xb[0]=0x7fedcba; xb[1]=0x0987654; xb[2]=0x3210fed; xb[3]=0x1a2b3c4 54 let ya: *i64 = sys_mmap((MSE_N+2)*8) as *i64; let yb: *i64 = sys_mmap((MSE_N+2)*8) as *i64 55 let sa: *i64 = sys_mmap((MSE_N+2)*8) as *i64; let sb: *i64 = sys_mmap((MSE_N+2)*8) as *i64 56 md_p("MSE-DH-GATE authored=organ (768-bit MODP, G=2)\n" as *u8) 57 mse_dh_public(xa, p, ya) // Ya = 2^Xa mod P 58 mse_dh_public(xb, p, yb) // Yb = 2^Xb mod P 59 mse_dh_shared(yb, xa, p, sa) // Sa = Yb^Xa mod P 60 mse_dh_shared(ya, xb, p, sb) // Sb = Ya^Xb mod P 61 let p_ok: i64 = md_nonzero(p, MSE_N) 62 let ya_ok: i64 = md_nonzero(ya, MSE_N); let yb_ok: i64 = md_nonzero(yb, MSE_N) 63 var y_diff: i64 = 0; if md_eq(ya, yb, MSE_N) == 0 { y_diff = 1 } // distinct keys => distinct pubkeys 64 let s_ok: i64 = md_nonzero(sa, MSE_N) 65 let s_agree: i64 = md_eq(sa, sb, MSE_N) // THE DH property 66 md_p(" prime_loaded=" as *u8); md_p("1" as *u8); md_p(" (top limb=" as *u8) 67 // show top limb of P (should be 0xFFFFFFFF) + top limb of the shared secret to prove real bignum values 68 let hx: *u8 = "0123456789abcdef" as *u8; let ob: *u8 = sys_mmap(16); var v: i64 = p[MSE_N-1]&0xFFFFFFFF; var k: i64=0; while k<8 { ob[7-k]=hx[(v>>(k*4))&0xf]; k=k+1 } sys_write(1, ob, 8); md_p(")\n" as *u8) 69 md_p(" pubkeys_nonzero=" as *u8); if ya_ok==1 { if yb_ok==1 { md_p("1" as *u8) } else { md_p("0" as *u8) } } else { md_p("0" as *u8) } 70 md_p(" pubkeys_differ=" as *u8); md_p(if_s(y_diff)) 71 md_p(" shared_nonzero=" as *u8); md_p(if_s(s_ok)) 72 md_p(" SHARED_SECRET_AGREES=" as *u8); md_p(if_s(s_agree)); md_p("\n" as *u8) 73 var allok: i64=0 74 if p_ok==1 { if ya_ok==1 { if yb_ok==1 { if y_diff==1 { if s_ok==1 { if s_agree==1 { allok=1 } } } } } } 75 if allok==1 { md_p("MSE-DH-GATE verdict=GREEN (both parties derived the identical DH shared secret)\n" as *u8); sys_exit(0); return 0 } 76 md_p("MSE-DH-GATE verdict=RED\n" as *u8); sys_exit(1); return 1 77}