nx_argon2id.nx
buildroot/runtime/nx_argon2id.nx
about
nx_argon2id.nx -- RFC 9106 Argon2id orchestrator (p=1, single-lane).
The substrate's memory-hard password hashing primitive. Composes:
- nx_blake2b.nx BLAKE2b-512 core hash
- nx_blake2b_long.nx RFC 9106 sec 3.4 variable-length H'
- nx_argon2_block.nx RFC 9106 sec 3.5/3.6 G compression + P
===== Why Argon2id =============================================
Argon2id (RFC 9106) is the WINNER of the Password Hashing
Competition (PHC). Intentionally hostile to AI / GPU / ASIC
attackers via memory hardness (each G call reads two 1024-byte
blocks from a configurably-sized matrix), integer-multiply
within GB (punishes weak 32-bit-mul hardware), and hybrid
Argon2i (first half pass) + Argon2d (rest) indexing for
side-channel + tradeoff resistance both.
===== Scope of this version (v1) ================================
- Parallelism: p = 1 ONLY (single-lane). Multi-lane queued.
- Type: Argon2id only (Argon2d / Argon2i variants share 90%
of code; will land as a single flag if needed).
- Version: 0x13 (RFC 9106) only.
- Memory: m_kib >= 8, multiple of 4 (sync-point alignment).
- Iterations: t >= 1.
- Output: tag_len in [4, 2^32 - 1].
===== Verdict scope ============================================
- All component bricks (BLAKE2b, H', G) are KAT-verified
or algebraic-property-verified.
- Argon2id END-TO-END output is NOT yet cross-validated
against argon2_ref C reference. Sensitivity tests prove
orchestrator wiring is correct + every parameter influences
the tag.
- Per cardinal feedback-honest-perf-verdict-no-aspirational-
claims: verdict = NOT_YET_EVALUATED until cross-validation
lands. Don't yet trust for production password storage.
dependencies 3 imports · 10 importers
imports: nx_blake2b.nxnx_blake2b_long.nxnx_argon2_block.nx
imported by: _ar2_minrepro.nx_ar2_perf_probe.nxnx_argon2id_b0_bisect.nxnx_argon2id_h0_bisect.nxnx_argon2id_t1_xvalidate.nxnx_argon2id_test.nxnx_argon2id_xvalidate_test.nxnx_cms_pw.nxnx_machine_key.nxnx_opaque_core.nx
structs
| 101 | struct NxArgon2idCtx |
consts
| 63 | const NX_MAGIC_1024: i64 = 1024 |
| 64 | const NX_MAGIC_1100: i64 = 1100 |
| 65 | const NX_MAGIC_4294967295: i64 = 4294967295 |
| 69 | const NX_AR2_OK: i64 = 0 |
| 70 | const NX_AR2_BAD_PARALLELISM: i64 = 1 |
| 71 | const NX_AR2_BAD_MEMORY: i64 = 2 |
| 72 | const NX_AR2_BAD_ITERATIONS: i64 = 3 |
| 73 | const NX_AR2_BAD_TAG_LEN: i64 = 4 |
| 74 | const NX_AR2_BAD_ARG: i64 = 5 |
| 75 | const NX_AR2_VERDICT_N: i64 = 6 |
| 89 | const NX_AR2_BLOCK_BYTES: i64 = 1024 |
| 90 | const NX_AR2_VERSION: i64 = 0x13 // RFC 9106 |
| 91 | const NX_AR2_TYPE_ID: i64 = 2 |
| 93 | const NX_AR2_SYNC_POINTS: i64 = 4 // slices per lane |
| 122 | const NX_ARGON2ID_CTX_BYTES: i64 = 144 // 18 * 8 |
functions
| 77 | func nx_argon2id_verdict_name(v: i64) -> *u8 |
| 126 | func _ar2_write_le32(buf: *u8, off: i64, v: i64) -> i64 called by 1: _ar2_h0 |
| 134 | func _ar2_write_le64(buf: *u8, off: i64, v: i64) -> i64 called by 1: _ar2_gen_address_block |
| 146 | func _ar2_load_u64_le(buf: *u8, off: i64) -> i64 called by 1: nx_argon2id_hash |
| 159 | func _ar2_block_xor_into(dst: *u8, src: *u8) -> i64 called by 1: nx_argon2id_hash |
| 168 | func _ar2_block_copy(dst: *u8, src: *u8) -> i64 called by 1: nx_argon2id_hash |
| 177 | func _ar2_block_at(memory: *u8, block_idx: i64) -> *u8 called by 1: nx_argon2id_hash |
| 189 | func _ar2_lshr32(x: i64) -> i64 called by 1: _ar2_map_index |
| 196 | func _ar2_map_index(j1: i64, pool_size: i64) -> i64 |
| 207 | func _ar2_h0(ctx: *NxArgon2idCtx, |
| 242 | func _ar2_gen_address_block(ctx: *NxArgon2idCtx, |
| 275 | func nx_argon2id_hash(ctx: *NxArgon2idCtx, |