nx_poly1305.nx
buildroot/runtime/nx_poly1305.nx
about
poly1305.nx -- Bernstein's Poly1305 MAC (RFC 8439 variant).
license_tier: INDEPENDENT_REDERIVE
genealogy_id: international-research-sources/ietf/rfc_8439
One-time authenticator over prime p = 2^130 - 5. Takes a 256-bit
one-time key (128-bit r clamped + 128-bit s), a message of any
length, and produces a 16-byte tag that is unforgeable under a
unique-per-message key assumption.
Why Poly1305:
- Proven secure in the one-time-key model (Bernstein 2005).
- Pairs with ChaCha20 to form the RFC 8439 AEAD construction
(ChaCha20-Poly1305), the primary TLS 1.3 cipher suite that
avoids AES cache-side-channel concerns.
- Naturally constant-time on this design: only modular
multiplication and addition, no branches on key/message
bits. (Some implementations use table lookups for
performance -- we avoid those for side-channel reasons.)
- Under Grover's algorithm a 128-bit MAC has 64-bit effective
security against quantum second-preimage -- that's marginal,
but second-preimage on a MAC isn't a practical attack; the
one-time-key property is what matters.
Arithmetic representation:
r and acc live as 5 x 26-bit limbs (total ~130 bits). Each
limb fits in i64 with headroom; partial products during
multiplication sum to at most ~5 * 2^52 = 2^54.3, still in
i64 range. After multiplication we carry-propagate and
reduce modulo p = 2^130 - 5 via the standard Bernstein trick
(multiply high bits by 5, add back to low).
Invariants:
P1 No branch depends on secret data (key or message bytes).
P2 The message is processed exactly once per block; padding
of the final short block is explicit (append 0x01, zero-
extend), no early exit.
P3 The r-clamp (RFC 8439 ยง2.5) is applied once at key setup;
never reapplied mid-stream so no key material leaks.
P4 Caller guarantees a *fresh* 256-bit key per message.
dependencies 1 imports · 6 importers
imports: nx_syscalls.nx
imported by: nx_aead.nxnx_aead_bench.nxnx_chacha20_poly1305.nxnx_poly1305_test.nxnx_poly1305_tput_probe.nxnx_ssh_lib.nx
structs
| none |
consts
| none |
functions
| 73 | func p_load_u32_le(buf: *u8, off: i64) -> i64 {
called by 1: poly1305_mac |
| 82 | func p_store_u32_le(buf: *u8, off: i64, v: i64) -> i64 {
called by 1: poly1305_mac |
| 95 | func poly1305_clamp(r: *u8) -> i64 {
called by 1: poly1305_mac |
| 117 | func poly1305_mac(key: *u8, msg: *u8, n: i64, tag: *u8) -> i64 { |
| 317 | func poly1305_tag_equal(a: *u8, b: *u8) -> i64 { |