code wiki / _hdl_build / nx_social_recovery_gate.nx
nx_social_recovery_gate.nx source
↩ module page · 82 lines · 3571 B
1// nx_social_recovery_gate.nx -- REFEREE for elderly-friendly social recovery (N=3 contacts, K=2 quorum over a
2// 256-bit secret). Security code MUST prove the quorum holds AND that less-than-quorum learns nothing.
3// T1 contacts {1,2} reconstruct == secret T4 a single share (K-1) != secret (no quorum -> nothing)
4// T2 contacts {1,3} reconstruct == secret T5 a tampered share != secret (one bad share = garbage)
5// T3 contacts {2,3} reconstruct == secret
6// GREEN iff T1..T5. Sovereign: nx_social_recovery + nx_vault_shamir + nx_csprng + nx_syscalls. license_tier: ORIGINAL
7import "nx_social_recovery.nx"
8import "nx_syscalls.nx"
9
10func 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 }
11func g_row(name: *u8, ok: i64) -> i64 {
12 if ok == 1 { g_w(" PASS " as *u8) }
13 if ok != 1 { g_w(" FAIL " as *u8) }
14 g_w(name)
15 g_w("\n" as *u8)
16 return ok
17}
18func g_eq32(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while i < SR_KEY_BYTES { if (a[i] as i64) != (b[i] as i64) { return 0 } i = i + 1 } return 1 }
19
20// load contacts a,b (0-based) into xs/shares_in for a k=2 reconstruct.
21func g_pick2(shares: *i64, a: i64, b: i64, xs: *i64, sin: *i64) -> i64 {
22 xs[0] = a + 1
23 xs[1] = b + 1
24 var c: i64 = 0
25 while c < SR_CHUNKS {
26 sin[0 * SR_CHUNKS + c] = shares[a * SR_CHUNKS + c]
27 sin[1 * SR_CHUNKS + c] = shares[b * SR_CHUNKS + c]
28 c = c + 1
29 }
30 return 0
31}
32
33func main() -> i64 {
34 g_w("social-recovery gate: N=3 trusted contacts, K=2 quorum over a 256-bit secret\n" as *u8)
35 let secret: *u8 = sys_mmap(SR_KEY_BYTES)
36 var i: i64 = 0
37 while i < SR_KEY_BYTES { secret[i] = ((i * 7 + 3) & 0xff) as u8; i = i + 1 }
38
39 let shares: *i64 = sys_mmap(3 * SR_CHUNKS * 8) as *i64
40 if nx_sr_split(secret, 3, 2, shares) != 0 { g_w("SPLIT FAIL\n" as *u8); sys_exit(1) }
41
42 let xs: *i64 = sys_mmap(2 * 8) as *i64
43 let sin: *i64 = sys_mmap(2 * SR_CHUNKS * 8) as *i64
44 let rec: *u8 = sys_mmap(SR_KEY_BYTES)
45 var pass: i64 = 0
46
47 g_pick2(shares, 0, 1, xs, sin)
48 nx_sr_reconstruct(2, xs, sin, rec)
49 pass = pass + g_row("T1 contacts {1,2} -> reconstruct == secret\x00" as *u8, g_eq32(rec, secret))
50
51 g_pick2(shares, 0, 2, xs, sin)
52 nx_sr_reconstruct(2, xs, sin, rec)
53 pass = pass + g_row("T2 contacts {1,3} -> reconstruct == secret\x00" as *u8, g_eq32(rec, secret))
54
55 g_pick2(shares, 1, 2, xs, sin)
56 nx_sr_reconstruct(2, xs, sin, rec)
57 pass = pass + g_row("T3 contacts {2,3} -> reconstruct == secret\x00" as *u8, g_eq32(rec, secret))
58
59 // ---- T4: a single share (K-1) reveals NOTHING -> != secret ----
60 let xs1: *i64 = sys_mmap(8) as *i64
61 xs1[0] = 1
62 let sin1: *i64 = sys_mmap(SR_CHUNKS * 8) as *i64
63 var c4: i64 = 0
64 while c4 < SR_CHUNKS { sin1[c4] = shares[0 * SR_CHUNKS + c4]; c4 = c4 + 1 }
65 nx_sr_reconstruct(1, xs1, sin1, rec)
66 var t4: i64 = 0
67 if g_eq32(rec, secret) == 0 { t4 = 1 }
68 pass = pass + g_row("T4 single share (K-1) -> NOT the secret\x00" as *u8, t4)
69
70 // ---- T5: a tampered share -> garbage != secret ----
71 g_pick2(shares, 0, 1, xs, sin)
72 sin[0] = sin[0] ^ 1
73 nx_sr_reconstruct(2, xs, sin, rec)
74 var t5: i64 = 0
75 if g_eq32(rec, secret) == 0 { t5 = 1 }
76 pass = pass + g_row("T5 tampered share -> garbage, NOT the secret\x00" as *u8, t5)
77
78 if pass == 5 { g_w("SOCIAL-RECOVERY GATE GREEN 5/5 (quorum rebuilds exactly; less-than-quorum learns nothing)\n" as *u8); sys_exit(0) }
79 g_w("SOCIAL-RECOVERY GATE RED\n" as *u8)
80 sys_exit(1)
81 return 1
82}