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}