nx_sha3.nx
buildroot/runtime/nx_sha3.nx
about
sha3.nx -- FIPS 202 SHA3-256 (Keccak-f[1600], rate=1088 bits).
license_tier: INDEPENDENT_REDERIVE
genealogy_id: international-research-sources/nist/fips_202
Quantum-safe companion to sha256.nx. Under Grover's algorithm both
SHA-256 and SHA3-256 have ~128-bit collision resistance on a quantum
adversary, which remains secure -- but SHA-3 is the primitive used
internally by NIST post-quantum schemes (ML-KEM FIPS 203, ML-DSA
FIPS 204, SLH-DSA FIPS 205), so shipping it here is the prerequisite
for every quantum-safe KEM/signature we'll add later.
Design:
- State: 25 * u64 = 1600 bits, laid out as a 5x5 lane grid A[x,y]
- Permutation: 24 rounds of theta, rho, pi, chi, iota
- Padding: SHA-3 domain separation byte 0x06, trailing 0x80
- Rate for SHA3-256: r = 1088 bits = 136 bytes; capacity c = 512
- Output: 32 bytes (first 256 bits of the state after finalisation)
Reference: FIPS PUB 202, sections 3.2-3.3. Known answer:
sha3_256("abc") =
3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532
This implementation:
- Pure NishiLang; no C interop; no libc.
- Uses only arithmetic + bit ops (XOR, AND, NOT, rotate-left)
defined on i64; 1600-bit state lives in a 25-entry i64 array.
- Sequential round loop; no table lookups on secret data.
Timing-side-channel stance: Keccak-f is naturally constant-time
when compiled straight from the spec. The only operations are
XOR, AND, NOT, and rotate-left -- all secret-independent in time.
No S-box table, no conditional on state bits. Safe to handle
secret data directly.
nx_safety_envelope:
intended_use: "SHA-3 / Keccak hash + SHAKE XOF -- post-
SHA-2-collision migration target, also
used as CSPRNG output stream"
sil_target: SIL3
dependencies 2 imports · 0 importers
imports: nx_syscalls.nxnx_bits.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 66 | const RC0: i64 = 0x0000000000000001 |
| 67 | const RC1: i64 = 0x0000000000008082 |
| 68 | const RC2: i64 = 0x800000000000808A |
| 69 | const RC3: i64 = 0x8000000080008000 |
| 70 | const RC4: i64 = 0x000000000000808B |
| 71 | const RC5: i64 = 0x0000000080000001 |
| 72 | const RC6: i64 = 0x8000000080008081 |
| 73 | const RC7: i64 = 0x8000000000008009 |
| 74 | const RC8: i64 = 0x000000000000008A |
| 75 | const RC9: i64 = 0x0000000000000088 |
| 76 | const RC10: i64 = 0x0000000080008009 |
| 77 | const RC11: i64 = 0x000000008000000A |
| 78 | const RC12: i64 = 0x000000008000808B |
| 79 | const RC13: i64 = 0x800000000000008B |
| 80 | const RC14: i64 = 0x8000000000008089 |
| 81 | const RC15: i64 = 0x8000000000008003 |
| 82 | const RC16: i64 = 0x8000000000008002 |
| 83 | const RC17: i64 = 0x8000000000000080 |
| 84 | const RC18: i64 = 0x000000000000800A |
| 85 | const RC19: i64 = 0x800000008000000A |
| 86 | const RC20: i64 = 0x8000000080008081 |
| 87 | const RC21: i64 = 0x8000000000008080 |
| 88 | const RC22: i64 = 0x0000000080000001 |
| 89 | const RC23: i64 = 0x8000000080008008 |
functions
| 92 | func sha3_rc(r: i64) -> i64 {
called by 1: keccak_round |
| 121 | func sha3_rho(i: i64) -> i64 {
called by 1: keccak_round |
| 152 | func rotl64(x: i64, r: i64) -> i64 { |
| 157 | func lane_at(state: *i64, x: i64, y: i64) -> i64 {
called by 1: keccak_round |
| 161 | func lane_set(state: *i64, x: i64, y: i64, v: i64) -> i64 {
called by 1: keccak_round |
| 168 | func keccak_round(state: *i64, scratch: *i64, round_idx: i64) -> i64 { |
| 239 | func keccak_permute(state: *i64, scratch: *i64) -> i64 { |
| 253 | func sha3_256(in_bytes: *u8, n: i64, out: *u8) -> i64 { |
| 319 | func main() -> i64 { |