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}