code wiki / (root) / nx_p256_field_inv.nx

nx_p256_field_inv.nx

buildroot/runtime/nx_p256_field_inv.nx

4892 B138 linesdepth 5pulls 6 transitivereach 743 importersview sourcekind tooltopic p256
docsdependenciesstructsconstsfunctions

about

nx_p256_field_inv.nx -- P-256 prime-field modular inverse via Fermat's little theorem. Phase 0b §I.3 piece 1d of the ECDSA-P256 arc: ✓ 0. u256 big-int (6ff89dd8) ✓ 1. p256_field add/sub/neg (133f16a1) ✓ 1b. u256 wide multiplication (ddb0994a) ✓ 1c. p256_field mul + sq (d295c0a3) ✓ 1d. p256_field inverse (THIS commit) - 2. p256_point ops (queued) - 3. p256_scalar mod n (queued) - 4. ecdsa_p256 verify (queued) Algorithm: Fermat's little theorem. For prime p and nonzero a: a^(p-1) = 1 (mod p) => a^(p-2) = a^(-1) (mod p) We compute a^(p-2) via straightforward left-to-right binary square-and-multiply over the 256 bits of (p-2). This is the most-portable form -- no addition-chain optimization, no constant-time guarantee. An optimized addition-chain variant (~30 mults vs ~128 here) is queued for piece 1d-fast. p-2 has 128 set bits in its 256-bit representation: bits 255..224 set (32 bits, top of p) bit 192 set (1 bit, "+ 2^192" in p) bits 95..32 set (64 bits, low 96 bits of p) bits 31, 30, ..., 2 set (30 bits) bit 0 set (lowest bit; bit 1 clear because -2) So 256 squarings + 128 multiplications = ~384 field ops per inverse. With our slow p256_field_mul at ~4100 limb-ops per mul, that's ~1.5M limb-ops per inverse. Each ECDSA verify uses ONE inverse (s^(-1) mod n -- but that's via the scalar modulus n, not p; this field inverse is used during point arithmetic's final-step Jacobian-to-affine conversion). Public API: p256_field_load_p_minus_2(out) p256_field_inv(out, a) p256_field_bit_at(limbs, bit_pos) -> 0|1 (helper)

dependencies 4 imports · 6 importers

nx_syscalls.nx nx_u256.nx nx_p256_field.nx nx_p256_field_mul.nx nx_p256_field_inv.nx nx_h2c_p256.nx nx_opaque_core.nx nx_p256_field_inv_test.nx nx_p256_point.nx nx_p256_point_test.nx nx_voprf.nx

imports: nx_syscalls.nxnx_u256.nxnx_p256_field.nxnx_p256_field_mul.nx

imported by: nx_h2c_p256.nxnx_opaque_core.nxnx_p256_field_inv_test.nxnx_p256_point.nxnx_p256_point_test.nxnx_voprf.nx

structs

none

consts

none

functions

74func p256_field_load_p_minus_2(out: *i64) -> i64
called by 2: p256_field_invmain
88func p256_field_bit_at(limbs: *i64, bit_pos: i64) -> i64
107func p256_field_inv(out: *i64, a: *i64) -> i64
136func main() -> i64