code wiki / _hdl_build / nx_connect_idage.nx
nx_connect_idage.nx source
↩ module page · 170 lines · 9447 B
1// nx_connect_idage.nx -- R3 of CONNECT: the SAFETY SPINE -- privacy-preserving age assurance +
2// re-registration-resistant identity. This closes the gap that R1/R2's minor<->romance walls
3// currently TRUST self-declared age. The honest exceed axes: PRIVACY-PRESERVING (vs Tinder/Bumble
4// ID-hoarding) and RE-REG-RESISTANT (vs Tandem's defeated photo-verify, banned users re-register).
5//
6// PROTOCOL (what this rung proves, by construction):
7// 1. A trusted issuer attests only an AGE BAND (adult/minor) -- never sends us DOB/name/ID.
8// 2. We VERIFY the attestation, then derive a SERVICE-SCOPED pseudonym from the issuer's subject
9// ref + our secret service salt, and STORE ONLY {age_band, scoped_pseudonym}. Raw PII never
10// reaches us; the issuer's subject ref is never stored (only the one-way scoped pseudonym).
11// 3. UNLINKABILITY: the same person at a DIFFERENT service gets a DIFFERENT, uncorrelatable
12// pseudonym (service-scoping). STABILITY within our service enables re-reg resistance.
13// 4. RE-REG RESISTANCE: bans are keyed by the scoped pseudonym (bound to verified identity), so a
14// banned user cannot evade by changing email/device -- only by defrauding the issuer.
15//
16// HONESTY (no overclaim): the issuer attestation is checked here with a SYMMETRIC keyed-hash MAC as
17// a STAND-IN for the production ASYMMETRIC issuer signature (ecosystem ed25519 verify w/ issuer
18// public key), and pseudonyms use a modular multiplicative hash as a STAND-IN for a CRYPTOGRAPHIC
19// hash (ecosystem SHA-256/BLAKE) for true preimage/collision resistance. Both are NAMED FOLLOW-ONS.
20// This rung proves the PRIVACY ARCHITECTURE (minimization, service-scoped unlinkability, identity-
21// bound banning) -- NOT cryptographic strength -> census cells flip to PRESENT, never PARITY/EXCEEDS.
22// 8 checks incl. 3 negative controls. 100% sovereign. license_tier: ORIGINAL expect_exit: 0
23import "nx_syscalls.nx"
24const ADULT_MAGIC_1000000: i64 = 1000000
25const ADULT_MAGIC_1990: i64 = 1990
26const ADULT_MAGIC_2010: i64 = 2010
27const ADULT_MAGIC_31337: i64 = 31337
28const ADULT_MAGIC_55555: i64 = 55555
29const ADULT_MAGIC_99999: i64 = 99999
30const ADULT_MAGIC_700001: i64 = 700001
31const ADULT_MAGIC_700002: i64 = 700002
32
33const HP: i64 = 1000000007 // hash modulus (prime). production: 256-bit cryptographic hash.
34const HA: i64 = 2654435761
35const HB: i64 = 2246822519
36const HC: i64 = 540041351
37const HD: i64 = 700000001
38const ADULT_AGE: i64 = 18
39const NOW_YEAR: i64 = 2026
40const BAND_ADULT: i64 = 1
41const BAND_MINOR: i64 = 0
42
43func sw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
44func sn(v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m;sys_write(1,"-" as *u8,1)} let t: *u8=sys_mmap(28); 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; while i<k{bb[i]=t[k-1-i];i=i+1} sys_write(1,bb,k); return 0 }
45
46func modp(h: i64) -> i64 { return h - (h/HP)*HP } // h positive throughout
47
48// modular multiplicative hash w/ avalanche (stand-in for a cryptographic hash)
49func hmix(x: i64) -> i64 {
50 var h: i64 = modp(x + HC)
51 h = modp(h*HA)
52 h = modp(h + HD)
53 h = modp(h*HB)
54 return h
55}
56
57// service-scoped, one-way pseudonym from issuer subject ref + our secret service salt
58func pseudo(subject: i64, salt: i64) -> i64 {
59 let a: i64 = hmix(subject)
60 return hmix(a + salt)
61}
62
63// NEG-CONTROL twin: the naive scheme stores the raw issuer subject id (ignores scoping) -> linkable
64func naive_id(subject: i64, salt: i64) -> i64 { return subject }
65
66// issuer attestation MAC over (subject, age_band) keyed by issuer secret (symmetric stand-in for a signature)
67func attest_mac(subject: i64, band: i64, secret: i64) -> i64 { return hmix(subject + band*ADULT_MAGIC_1000000 + secret) }
68func verify_attest(subject: i64, band: i64, secret: i64, presented: i64) -> i64 {
69 if attest_mac(subject, band, secret)==presented { return 1 }
70 return 0
71}
72
73// issuer-side: derive age band from DOB. The DOB stays with the issuer and NEVER reaches us.
74func band_from_year(birth_year: i64, now_year: i64, adult_age: i64) -> i64 {
75 if (now_year - birth_year) >= adult_age { return BAND_ADULT }
76 return BAND_MINOR
77}
78
79func is_member(p: i64, set: *i64, n: i64) -> i64 {
80 var i: i64=0
81 while i<n { if set[i]==p { return 1 } i=i+1 }
82 return 0
83}
84
85func tcheck(pass: i64, label: *u8, fails: *i64) -> i64 {
86 sw(" " as *u8); sw(label); sw(": " as *u8)
87 if pass==1 { sw("PASS\n" as *u8) } else { sw("FAIL\n" as *u8); fails[0]=fails[0]+1 }
88 return 0
89}
90
91func main() -> i64 {
92 let fails: *i64 = sys_mmap(16) as *i64
93 fails[0]=0
94
95 // synthetic actors (ZERO real PHI). issuer subject refs are secret to the issuer; DOB/ID never sent to us.
96 let subj_x: i64 = 101 // PERSON_X born ADULT_MAGIC_1990 -> adult
97 let subj_y: i64 = 202 // PERSON_Y born ADULT_MAGIC_2010 -> MINOR
98 let yr_x: i64 = ADULT_MAGIC_1990
99 let yr_y: i64 = ADULT_MAGIC_2010
100 let issuer_secret: i64 = ADULT_MAGIC_31337
101 let salt_us: i64 = ADULT_MAGIC_55555 // OUR service's secret scoping salt
102 let salt_other: i64 = ADULT_MAGIC_99999 // some OTHER service's salt
103
104 // issuer attests only the BAND:
105 let band_x: i64 = band_from_year(yr_x, NOW_YEAR, ADULT_AGE)
106 let band_y: i64 = band_from_year(yr_y, NOW_YEAR, ADULT_AGE)
107 let mac_x: i64 = attest_mac(subj_x, band_x, issuer_secret)
108
109 // we verify + derive what we STORE (only band + scoped pseudonym):
110 let ok_x: i64 = verify_attest(subj_x, band_x, issuer_secret, mac_x)
111 let pseu_x_us: i64 = pseudo(subj_x, salt_us)
112 let pseu_x_other: i64 = pseudo(subj_x, salt_other)
113 let pseu_y_us: i64 = pseudo(subj_y, salt_us)
114
115 sw("=== nx_connect_idage R3 -- privacy-preserving age assurance + re-reg-resistant identity ===\n" as *u8)
116 sw("we STORE only {age_band, scoped_pseudonym}. DOB/ID never reach us; issuer subject ref never stored.\n" as *u8)
117 sw(" PERSON_X band (1990) = " as *u8); sn(band_x); sw(" (adult)\n" as *u8)
118 sw(" PERSON_Y band (2010) = " as *u8); sn(band_y); sw(" (minor)\n" as *u8)
119 sw(" X pseudonym @ our service = " as *u8); sn(pseu_x_us); sw("\n" as *u8)
120 sw(" X pseudonym @ OTHER service = " as *u8); sn(pseu_x_other); sw(" (uncorrelatable w/ ours)\n" as *u8)
121 sw(" (production: ed25519 issuer signature + cryptographic hash; here MAC+modular-hash stand-ins)\n" as *u8)
122 sw("-- gate checks --\n" as *u8)
123
124 // T1: valid issuer attestation verifies
125 tcheck(ok_x, "T1 valid issuer age attestation verifies" as *u8, fails)
126
127 // T2: NEG-CONTROL -- forged/tampered attestation rejected (wrong mac AND wrong secret)
128 var t2: i64=0
129 if verify_attest(subj_x, band_x, issuer_secret, mac_x+1)==0 { if verify_attest(subj_x, band_x, issuer_secret+1, mac_x)==0 { t2=1 } }
130 tcheck(t2, "T2 NEG-CONTROL forged/tampered attestation rejected (liar-kill)" as *u8, fails)
131
132 // T3: data-minimization -- what we store is NOT the DOB and NOT the raw subject id
133 var t3: i64=0
134 if pseu_x_us!=yr_x { if pseu_x_us!=subj_x { t3=1 } }
135 tcheck(t3, "T3 data-minimization: stored pseudonym is neither DOB nor raw id" as *u8, fails)
136
137 // T4: unlinkability across services + NEG-CONTROL (naive raw-id is identical across services)
138 var t4: i64=0
139 if pseu_x_us!=pseu_x_other { if naive_id(subj_x,salt_us)==naive_id(subj_x,salt_other) { t4=1 } }
140 tcheck(t4, "T4 unlinkable across services (naive raw-id would be linkable)" as *u8, fails)
141
142 // T5: within-service stability (deterministic) -- required for re-reg resistance
143 var t5: i64=0; if pseudo(subj_x,salt_us)==pseu_x_us { t5=1 }
144 tcheck(t5, "T5 within-service pseudonym is stable (re-derivable)" as *u8, fails)
145
146 // T6: distinct subjects -> distinct pseudonyms
147 var t6: i64=0; if pseu_x_us!=pseu_y_us { t6=1 }
148 tcheck(t6, "T6 distinct identities -> distinct pseudonyms" as *u8, fails)
149
150 // T7: age band correct + feeds the R1/R2 walls (adult=1, minor=0) instead of self-declared age
151 var t7: i64=0; if band_x==BAND_ADULT { if band_y==BAND_MINOR { t7=1 } }
152 tcheck(t7, "T7 age band correct (now feeds the minor<->romance walls, not self-declared)" as *u8, fails)
153
154 // T8: re-registration resistance -- ban keyed by scoped pseudonym; new account same identity is caught.
155 // NEG-CONTROL: ban-by-email lets the same person back in with a new email.
156 let banset: *i64 = sys_mmap(64) as *i64
157 banset[0]=pseu_x_us // PERSON_X gets banned (identity-bound)
158 let rereg_blocked: i64 = is_member(pseudo(subj_x,salt_us), banset, 1) // they re-enroll, same identity
159 let emailban: *i64 = sys_mmap(64) as *i64
160 emailban[0]=ADULT_MAGIC_700001 // ban their FIRST email hash
161 let rereg_email: i64 = is_member(ADULT_MAGIC_700002, emailban, 1) // they return with a NEW email
162 var t8: i64=0; if rereg_blocked==1 { if rereg_email==0 { t8=1 } }
163 tcheck(t8, "T8 re-reg resistance: identity-bound ban catches new account (email-ban would not)" as *u8, fails)
164
165 sw(" fails=" as *u8); sn(fails[0]); sw("\n" as *u8)
166 if fails[0]==0 { sw("VERDICT: GREEN (privacy architecture proven; crypto primitives = named follow-on; not over-claimed)\n" as *u8); sys_exit(0) }
167 sw("VERDICT: RED\n" as *u8)
168 sys_exit(1)
169 return 1
170}