nx_cap_keygen_gate.nx source
↩ module page · 67 lines · 4635 B
1// nx_cap_keygen_gate.nx -- proves nx_cap_keygen provisions a REAL CSPRNG signing secret that (a) is 256-bit hex,
2// (b) lands on disk 0600 byte-exact with no trailing newline, (c) has real entropy (two draws differ), (d) is
3// fail-safe (refuses a silent overwrite), and -- the composition that matters -- (e) actually WORKS as an HMAC
4// signing key: a capability minted with it VERIFIES, and (f) is independent: a token signed by one key is DENIED
5// under another (unforgeable across keys). Closes GAP 2 of the MCP grant and ties it to GAP 1 (mint) + verify.
6// license_tier: ORIGINAL expect_exit: 0
7import "nx_cap_keygen.nx" // ck_provision + CK_* (+ transitive nx_csprng, nx_syscalls)
8import "nx_cap_token.nx" // capt_issue / capt_verify / CAPT_OK / CAPT_DENY_MAC
9import "nx_gate.nx" // gw / gn
10
11const KG_PATH: *u8 = "/tmp/nx_capkeygen_gate.key" as *u8
12
13func kg_is_hex(c: i64) -> i64 { if c >= 48 { if c <= 57 { return 1 } } if c >= 97 { if c <= 102 { return 1 } } return 0 }
14func kg_all_hex(s: *u8, n: i64) -> i64 { var i: i64 = 0; while i < n { if kg_is_hex(s[i] as i64) == 0 { return 0 } i = i + 1 } return 1 }
15func kg_eqn(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 }
16
17func kg_expect(actual: i64, expected: i64, pass: *i64, tot: *i64, label: *u8) -> i64 {
18 tot[0] = tot[0] + 1
19 if actual == expected { pass[0] = pass[0] + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL got=" as *u8); gn(actual); gw(" want=" as *u8); gn(expected); gw("] " as *u8) }
20 gw(label); gw("\n" as *u8)
21 return 0
22}
23
24func main() -> i64 {
25 gw("=== nx_cap_keygen_gate: CSPRNG signing-secret provisioning (GAP 2), proven to sign valid caps ===\n" as *u8)
26 __syscall(87, KG_PATH, 0, 0, 0, 0, 0) // unlink any stale file (ignore result)
27 let pbox: *i64 = sys_mmap(16) as *i64; pbox[0] = 0
28 let tbox: *i64 = sys_mmap(16) as *i64; tbox[0] = 0
29
30 // T1: provision a fresh keyfile
31 let k1: *u8 = sys_mmap(128); let l1: *i64 = sys_mmap(16) as *i64
32 let r1: i64 = ck_provision(KG_PATH, 1, k1, l1)
33 kg_expect(r1, CK_OK, pbox, tbox, "T1a provision (fresh) -> CK_OK" as *u8)
34 kg_expect(l1[0], 64, pbox, tbox, "T1b secret is 64 hex chars (256-bit)" as *u8)
35 kg_expect(kg_all_hex(k1, 64), 1, pbox, tbox, "T1c all chars are lowercase hex [0-9a-f]" as *u8)
36
37 // T2: the on-disk file is byte-exact to the returned key (64 bytes, no trailing newline)
38 let szp: *i64 = sys_mmap(16) as *i64
39 let disk: *u8 = sys_read_file(KG_PATH, szp)
40 var t2: i64 = 0
41 if (disk as i64) != 0 { if szp[0] == 64 { if kg_eqn(disk, k1, 64) == 1 { t2 = 1 } } }
42 kg_expect(t2, 1, pbox, tbox, "T2 keyfile on disk == returned secret, exactly 64 bytes (no newline)" as *u8)
43
44 // T3: entropy -- a second forced draw differs from the first (not a constant)
45 let k2: *u8 = sys_mmap(128); let l2: *i64 = sys_mmap(16) as *i64
46 let r3: i64 = ck_provision(KG_PATH, 1, k2, l2)
47 var differ: i64 = 0
48 if r3 == CK_OK { if kg_eqn(k1, k2, 64) == 0 { differ = 1 } }
49 kg_expect(differ, 1, pbox, tbox, "T3 second draw differs from the first (real entropy, not constant)" as *u8)
50
51 // T4: fail-safe -- provisioning over an existing file WITHOUT --force is refused (no silent rotate)
52 let k3: *u8 = sys_mmap(128); let l3: *i64 = sys_mmap(16) as *i64
53 let r4: i64 = ck_provision(KG_PATH, 0, k3, l3)
54 kg_expect(r4, CK_EXISTS, pbox, tbox, "T4 no-force over existing keyfile -> CK_EXISTS (no silent rotate)" as *u8)
55
56 // T5: COMPOSITION -- a capability minted with the GENERATED key verifies (the secret really is a working HMAC key)
57 let tok: *u8 = sys_mmap(1024)
58 let tn: i64 = capt_issue(k1, l1[0], "nx_mgmt_client" as *u8, 14, 9999999999, 7, tok, 1024)
59 kg_expect(capt_verify(k1, l1[0], tok, tn, "nx_mgmt_client" as *u8, 14, 1782000000), CAPT_OK, pbox, tbox, "T5 cap minted with the generated key VERIFIES (GAP2 secret drives GAP1 mint)" as *u8)
60
61 // T6: independence -- the SAME token does NOT verify under a DIFFERENT generated key (unforgeable across keys)
62 kg_expect(capt_verify(k2, l2[0], tok, tn, "nx_mgmt_client" as *u8, 14, 1782000000), CAPT_DENY_MAC, pbox, tbox, "T6 token from key#1 is DENIED under key#2 (keys independent, unforgeable)" as *u8)
63
64 gw("\n=== nx_cap_keygen_gate " as *u8); gn(pbox[0]); gw("/" as *u8); gn(tbox[0]); gw(" ===\n" as *u8)
65 if pbox[0] == tbox[0] { gw("CAP-KEYGEN GREEN -- CSPRNG 256-bit secret, 0600 byte-exact, real entropy, fail-safe, PROVEN to sign+verify caps (GAP 2 closed offline)\n" as *u8); sys_exit(0); return 0 }
66 gw("CAP-KEYGEN RED\n" as *u8); sys_exit(1); return 1
67}