code wiki / _hdl_build / nx_recover_gate.nx

nx_recover_gate.nx source

↩ module page · 61 lines · 4534 B

1// nx_recover_gate.nx -- proves the forgot-passphrase RECOVERY flow (olg_recover, the new seam over the KAT'd 2// nx_modern_auth_recover). Full lifecycle in-process (the socket path is already proven by nx_lan_signup_socket_gate): 3// register brad -> login(old pw) OK -> recover(mnemonic, NEW pw) OK + NEW mnemonic -> login(NEW pw) OK -> 4// login(OLD pw) REJECTED -> recover(OLD/rotated mnemonic) REJECTED (rotation = the old phrase can't be replayed). 5// GREEN iff every row matches. Durable -> knowledge/status/recover_gate.log. 6import "nx_opaque_login.nx" // olg_ctx_setup / olg_register / olg_login / olg_recover + NxAuthContext + NX_MAUTH_OK 7import "nx_syscalls.nx" 8 9func g_w(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 10func g_n(v: i64) -> i64 { var m: i64=v; if m<0{g_w("-" as *u8);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var i:i64=0; let o:*u8=sys_mmap(24); while i<k{o[i]=t[k-1-i];i=i+1} sys_write(1,o,k); return 0 } 11func g_row(id: *u8, ok: i64, pass: *i64) -> i64 { g_w(" " as *u8); g_w(id); g_w(": " as *u8); if ok==1 { g_w("OK\n" as *u8); pass[0]=pass[0]+1 } else { g_w("FAIL\n" as *u8) } return 0 } 12func gw(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 13func gtrunc(path: *u8) -> i64 { let fd: i64 = sys_openat_wr(path, 0x1a4); if fd>=0 { sys_close(fd) } return 0 } 14// 1 if the two byte ranges differ (length or content) -- proves the mnemonic rotated. 15func mn_differs(a: *u8, an: i64, b: *u8, bn: i64) -> i64 { if an != bn { return 1 } var i: i64=0; while i<an { if a[i]!=b[i] { return 1 } i=i+1 } return 0 } 16 17func main() -> i64 { 18 let pass: *i64 = sys_mmap(8) as *i64; pass[0]=0 19 g_w("=== NISHI RECOVER GATE (forgot-passphrase via BIP39 mnemonic; rotation enforced) ===\n" as *u8) 20 let keys: *u8 = "/tmp/nx_rec_keys.bin" as *u8 21 let store: *u8 = "/tmp/nx_rec_store.log" as *u8 22 gtrunc(keys); gtrunc(store) 23 let ctx: *NxAuthContext = sys_mmap(256) as *NxAuthContext 24 if olg_ctx_setup(ctx, keys, store, "nishi_site_admin" as *u8, 16, "recover test" as *u8, 12, 512, 3, 1) != 0 { 25 g_w("CTX-INIT-FAIL\n" as *u8); sys_exit(1); return 1 26 } 27 28 // register brad -> mnemonic M1 29 let m1: *u8 = sys_mmap(512); let m1n: *i64 = sys_mmap(16) as *i64 30 let reg_ok: i64 = (olg_register(ctx, "brad" as *u8, 4, "passOne1" as *u8, 8, m1, 512, m1n) == NX_MAUTH_OK) as i64 31 let b64: *u8 = sys_mmap(512); let b64n: *i64 = sys_mmap(16) as *i64 32 let login1: i64 = (olg_login(ctx, "brad" as *u8, 4, "passOne1" as *u8, 8, b64, 512, b64n) == NX_MAUTH_OK) as i64 33 34 // recover with M1 -> new passphrase + new mnemonic M2 35 let m2: *u8 = sys_mmap(512); let m2n: *i64 = sys_mmap(16) as *i64 36 let rec_ok: i64 = (olg_recover(ctx, "brad" as *u8, 4, m1, m1n[0], "passTwo2" as *u8, 8, m2, 512, m2n) == NX_MAUTH_OK) as i64 37 let rotated: i64 = mn_differs(m1, m1n[0], m2, m2n[0]) 38 39 let login2: i64 = (olg_login(ctx, "brad" as *u8, 4, "passTwo2" as *u8, 8, b64, 512, b64n) == NX_MAUTH_OK) as i64 40 let login_old_rej: i64 = (olg_login(ctx, "brad" as *u8, 4, "passOne1" as *u8, 8, b64, 512, b64n) != NX_MAUTH_OK) as i64 41 42 // recover AGAIN with the OLD (rotated) mnemonic -> must be REJECTED 43 let m3: *u8 = sys_mmap(512); let m3n: *i64 = sys_mmap(16) as *i64 44 let rec_old_rej: i64 = (olg_recover(ctx, "brad" as *u8, 4, m1, m1n[0], "passThree3" as *u8, 10, m3, 512, m3n) != NX_MAUTH_OK) as i64 45 46 g_w(" mnemonic bytes: M1="); g_n(m1n[0]); g_w(" M2="); g_n(m2n[0]); g_w("\n" as *u8) 47 g_row("register brad -> recovery mnemonic issued" as *u8, reg_ok, pass) 48 g_row("login with the original passphrase" as *u8, login1, pass) 49 g_row("recover (mnemonic + NEW passphrase) succeeds" as *u8, rec_ok, pass) 50 g_row("recovery ROTATES the mnemonic (M2 != M1)" as *u8, rotated, pass) 51 g_row("login with the NEW passphrase works" as *u8, login2, pass) 52 g_row("login with the OLD passphrase REJECTED" as *u8, login_old_rej, pass) 53 g_row("recover with the OLD (rotated) mnemonic REJECTED (no replay)" as *u8, rec_old_rej, pass) 54 55 g_w("RECOVER-GATE rows=7 pass="); g_n(pass[0]) 56 if pass[0]==7 { g_w(" verdict=GREEN\n" as *u8) 57 let lg: i64=sys_openat_append("knowledge/status/recover_gate.log" as *u8, 0x1a4) 58 if lg>=0 { gw(lg, "NISHI-RECOVER-GATE pass=7/7 verdict=GREEN\n" as *u8); sys_close(lg) } 59 sys_exit(0); return 0 } 60 g_w(" verdict=RED\n" as *u8); sys_exit(1); return 1 61}