code wiki / _hdl_build / nx_social_auth_recover.nx
nx_social_auth_recover.nx source
↩ module page · 45 lines · 2854 B
1// nx_social_auth_recover.nx -- the WIRING that makes elderly social recovery REAL: it connects the Shamir
2// family-quorum primitive (nx_social_recovery) to actual account recovery (nx_modern_auth_recover), via the
3// BIP39 codec. The recovery secret IS the entropy behind the user's issued mnemonic, so:
4// ENROLL: decode the issued mnemonic -> its 256-bit entropy -> Shamir-split across N trusted contacts (K
5// threshold). The USER HOLDS NOTHING; the family holds shares.
6// RECOVER: K contacts reconstruct the entropy -> re-encode the mnemonic -> nx_modern_auth_recover (sets a
7// new passphrase, rotates the mnemonic). K-1 reconstruct GARBAGE -> a wrong mnemonic -> refused.
8// After a recovery the mnemonic rotates, so the caller MUST re-split the new mnemonic (nx_sar_enroll_split)
9// for the next cycle. No seed phrase is ever handed to the user; the family quorum is the backup.
10// Composes nx_social_recovery + nx_bip39 + nx_modern_auth_flow. license_tier: ORIGINAL
11import "nx_social_recovery.nx"
12import "hub/nx_bip39.nx"
13import "hub/nx_modern_auth_flow.nx"
14import "nx_syscalls.nx"
15
16const NX_SAR_OK: i64 = 0
17const NX_SAR_BAD_MNEMONIC: i64 = 1 // the issued mnemonic didn't decode to 256-bit entropy
18const NX_SAR_RECOVER_FAILED: i64 = 2 // the reconstructed entropy didn't recover the account (e.g. < K shares)
19
20// ENROLL: split the entropy behind `mn` across n contacts, threshold k. shares_out = n rows x SR_CHUNKS i64.
21func nx_sar_enroll_split(mn: *u8, mn_n: i64, n: i64, k: i64, shares_out: *i64) -> i64 {
22 let ent: *u8 = sys_mmap(64)
23 let ebox: *i64 = sys_mmap(8) as *i64
24 ebox[0] = 0
25 if nx_bip39_decode(mn, mn_n, ent, 64, ebox) != NX_B39_OK { return 0 - NX_SAR_BAD_MNEMONIC }
26 if ebox[0] != SR_KEY_BYTES { return 0 - NX_SAR_BAD_MNEMONIC }
27 if nx_sr_split(ent, n, k, shares_out) != 0 { return 0 - NX_SAR_BAD_MNEMONIC }
28 return NX_SAR_OK
29}
30
31// RECOVER: k contacts (xs[], shares_in = k rows x SR_CHUNKS) reconstruct the entropy -> mnemonic ->
32// nx_modern_auth_recover(set new_pw, rotate). new_mn_out gets the NEW rotated mnemonic (RE-SPLIT it next).
33func nx_sar_recover(ctx: *NxAuthContext, handle: *u8, handle_n: i64,
34 k: i64, xs: *i64, shares_in: *i64,
35 new_pw: *u8, new_pw_n: i64,
36 new_mn_out: *u8, new_mn_cap: i64, new_mn_n_out: *i64) -> i64 {
37 let ent: *u8 = sys_mmap(64)
38 nx_sr_reconstruct(k, xs, shares_in, ent)
39 let mn: *u8 = sys_mmap(512)
40 let mnbox: *i64 = sys_mmap(8) as *i64
41 mnbox[0] = 0
42 if nx_bip39_encode(ent, SR_KEY_BYTES, mn, 512, mnbox) != NX_B39_OK { return 0 - NX_SAR_RECOVER_FAILED }
43 if nx_modern_auth_recover(ctx, handle, handle_n, mn, mnbox[0], new_pw, new_pw_n, new_mn_out, new_mn_cap, new_mn_n_out) != NX_MAUTH_OK { return 0 - NX_SAR_RECOVER_FAILED }
44 return NX_SAR_OK
45}