nx_kyber_sample_ntt_wasm.nx
buildroot/runtime/nx_kyber_sample_ntt_wasm.nx
about
nx_kyber_sample_ntt_wasm.nx -- FIPS 203 §4.2.1 SampleNTT (rejection sampling).
Turns a SHAKE128 byte stream into a uniformly-random NTT-domain
polynomial: 256 coefficients in Z_3329. The matrix A used in
ML-KEM-768 K-PKE keygen / encrypt is built from 9 such polynomials
(k * k = 9, k=3 for ML-KEM-768), one per (i, j) pair seeded by the
(rho || j || i) byte string SHAKE128'd into bytes.
Algorithm (FIPS 203 §4.2.1 Algorithm 4):
Read 3 bytes at a time from the SHAKE stream. Split into two 12-bit
values d1 = b0 | ((b1 & 0xf) << 8), d2 = (b1 >> 4) | (b2 << 4).
If d < q, accept as next coefficient. Otherwise discard and continue.
Stop when 256 coefficients have been accepted.
Browser-side glue:
1. SHAKE128.absorb(rho || j_byte || i_byte)
2. SHAKE128.squeeze(buf, buf_len) -- ~600 bytes usually enough
3. nx_kyber_sample_ntt(poly_out, buf, buf_len) -> n_consumed (>=0)
OR -1 if buffer too short (caller should squeeze more + retry)
API:
nx_kyber_sample_ntt(poly_out, buf, buf_len) -> i64
returns number of bytes consumed on success, -1 if buffer
too short to reach 256 accepted coefficients.
Verified: KAT against PQClean reference (a known SHAKE stream
produces a known polynomial).
license_tier: INDEPENDENT_REDERIVE
genealogy_id: international-research-sources/nist/fips_203
lineage_id: nishi_kyber_sample_ntt_wasm_q1
safe_shift_audit: no 64-bit rotations in this module
dependencies 0 imports · 0 importers
imports: none
imported by: nobody (leaf or entry point)
structs
| none |
consts
| 34 | const KYBER_Q: i64 = 3329 |
| 35 | const KYBER_N: i64 = 256 |
functions
| 37 | func _pstore(p: *u8, i: i64, v: i64) -> i64 called by 1: nx_kyber_sample_ntt |
| 48 | func nx_kyber_sample_ntt(poly: *u8, buf: *u8, buf_len: i64) -> i64 calls 1: _pstore |