nx_user_account_store.nx
buildroot/runtime/hub/nx_user_account_store.nx
about
nx_user_account_store.nx -- V-MODAUTH-4: durable OPAQUE account store + server key bundle.
What the server persists per user: the RegistrationRecord (129 bytes: client_public_key
|| masking_key || envelope). By OPAQUE's design this is NOT offline-crackable without
ALSO stealing the oprf_seed (held in the SEPARATE server key bundle file), and even
then every guess pays a full OPRF + memory-hard argon2id evaluation.
Storage doctrine (ADDITIVE-ONLY, per global rule 13): append-only text log, one
record per line, LATEST line for a user_id_hash wins. Re-registration appends a
superseding row; disable = append a row with is_current=0. History is never deleted.
A row is a single sys_write of < 400 bytes => atomic on the substrate (O_APPEND).
Line formats:
account log: A1 <user_id_hash:64hex> <is_current:1> <created_unix:16hex> <record:258hex>\n
key bundle: K1 <oprf_seed:64hex> <ake_priv:64hex> <ake_pub:66hex> <ed_priv:64hex> <ed_pub:64hex>\n
The key bundle file is the server's crown-jewel secret (oprf_seed + AKE private +
session-token signing key). It is created 0600 and MUST live OUTSIDE git-tracked
trees (caller passes the path; wiki wiring uses a data-dir path, never knowledge/).
COMPOSES: nx_syscalls (openat_append/read_file/fsync), nx_csprng,
hub/nx_opaque_core (DeriveDiffieHellmanKeyPair for the AKE keypair),
nx_ed25519_signature (pub_from_priv)
COMPOSED BY: hub/nx_modern_auth_flow (register stores, login looks up)
license_tier: ORIGINAL
dependencies 4 imports · 5 importers
imports: nx_syscalls.nxnx_csprng.nxnx_ed25519_signature.nxnx_opaque_core.nx
imported by: nx_account_cleanup.nxnx_mgmt_session_mint_gate.nxnx_modern_auth_flow.nxnx_opaque_login.nxnx_wiki_https_daemon_mv.nx
structs
| none |
consts
| 33 | const NX_UAS_OK: i64 = 0 |
| 34 | const NX_UAS_BAD_INPUT: i64 = 1460 |
| 35 | const NX_UAS_IO_FAILED: i64 = 1461 |
| 36 | const NX_UAS_NOT_FOUND: i64 = 1462 |
| 37 | const NX_UAS_DISABLED: i64 = 1463 // latest row for user has is_current=0 |
| 38 | const NX_UAS_MALFORMED: i64 = 1464 |
| 39 | const NX_UAS_KEYGEN_FAILED: i64 = 1465 |
| 41 | const NX_UAS_RECORD_BYTES: i64 = 129 // = NX_OPQ_RECORD_BYTES (sealed wire size) |
| 42 | const NX_UAS_LINE_BYTES: i64 = 344 // 2+1+64+1+1+1+16+1+258 = 345 incl \n |
| 43 | const NX_UAS_MAX_STORE_BYTES: i64 = 16777216 // 16 MiB scan cap (~48k rows) |
functions
| 47 | func _uas_hex_enc(src: *u8, n: i64, out: *u8) -> i64 |
| 58 | func _uas_nib(c: i64) -> i64 called by 1: _uas_hex_dec |
| 66 | func _uas_hex_dec(hexs: *u8, n: i64, out: *u8) -> i64 |
| 79 | func _uas_i64_hex16(v: i64, out: *u8) -> i64 called by 1: nx_uas_append |
| 91 | func nx_uas_append( called by 2: main_ma_register_credential calls 7: sys_mmap_uas_hex_enc_uas_i64_hex16sys_openat_appendsys_writesys_fsync+1 |
| 135 | func nx_uas_lookup( |
| 201 | func nx_uas_server_keys_load_or_init( called by 31: mainmainmainmainmainmain+25 calls 11: sys_mmapsys_read_file_uas_hex_decnx_csprng_fillnx_opq_derive_keypaired25519_pub_from_priv+5 |