nx_mtls_identity.nx
buildroot/runtime/nx_mtls_identity.nx
about
nx_mtls_identity.nx -- OPAQUE-bound client identity: derive the mTLS keypair + cert from export_key.
mTLS rung R5 of the NO-COOKIE session carrier -- the OPAQUE BINDING. After OPAQUE login, both client and
server hold the 32-byte export_key (RFC 9807) derived from the password proof. We HKDF-Expand it into a
deterministic Ed25519 identity keypair and mint a cert whose Subject CN = hex(user_id_hash). Consequences:
* the private key is NEVER stored server-side -- the client re-derives it from its own password proof
(sovereign, data-minimal: PRIV2 "no server-side correlation" preserved -- nothing new to store/leak);
* the identity is the SAME stable user_id_hash the OPAQUE/HR stack already keys on (SEC4 realm isolation);
* R6 maps the verified cert identity -> HR entitlements; the PKCS#12 packaging for browser import is R5b.
LIVE-CAPTURE NOTE: nx_modern_auth_login / olg_login currently DISCARD the export_key. R5b/R7 surfaces it
from the OPAQUE flow (additive out-param) so the daemon can mint + hand back the identity on login.
Composes nx_hkdf (export->key) + nx_x509_leaf_emit (R4 mint) + nx_ed25519_signature. license_tier: ORIGINAL expect_exit: 0
dependencies 6 imports · 2 importers
imports: nx_syscalls.nxnx_hkdf.nxnx_ed25519_signature.nxnx_x509.nxnx_x509_validate.nxnx_x509_leaf_emit.nx
imported by: nx_aw_mtls_inject_gate.nxnx_mtls_issue.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 21 | const NX_MAGIC_5869: i64 = 5869 |
| 22 | const NX_MAGIC_4096: i64 = 4096 |
| 24 | const NX_MID_OK: i64 = 0 |
| 25 | const NX_MID_ERR: i64 = 1 |
functions
| 29 | func nx_mtls_derive_identity_keypair(export_key_32: *u8, out_seed_32: *u8, out_pub_32: *u8) -> i64 |
| 38 | func nx_mid_hex(src: *u8, n: i64, out: *u8) -> i64 |
| 52 | func nx_mtls_mint_identity_cert( |
| 72 | func mid_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } |
| 73 | func mid_row(name: *u8, ok: i64) -> i64 { if ok == 1 { mid_w(" PASS " as *u8) } else { mid_w(" FAIL " as *u8) } mid_w(name); mid_w("\n" as *u8); return ok } |
| 74 | func mid_eq32(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while i < 32 { if a[i] != b[i] { return 0 } i = i + 1 } return 1 } called by 1: main |
| 75 | func mid_find(hay: *u8, hn: i64, needle: *u8, nn: i64) -> i64 |
| 86 | func main() -> i64 |