Technical Deep Dive

Cryptography

Understanding the lattice-based primitives, mathematical foundations, and implementation details of Po8's post-quantum cryptographic substrate.

From Curves to Lattices

The security of traditional cryptography (RSA, ECC) relies on the hardness of integer factorization and the discrete logarithm problem. Shor's algorithm breaks both in polynomial time on a quantum computer.

Problem Classical Quantum Status
Integer Factorization (RSA) Sub-exponential Polynomial (Shor) Broken
Discrete Log (ECC) Exponential Polynomial (Shor) Broken
Learning With Errors Exponential Exponential Secure
Shortest Vector Problem Exponential Exponential Secure

Module-Learning With Errors (MLWE)

Po8 builds on the MLWE problem, which forms the foundation of Kyber and Dilithium.

b = As + e (mod q)

Where:

  • A is a public matrix
  • s is the secret vector
  • e is a small error vector (noise)
  • q = 3329 (chosen for NTT optimization)

Without the error term, solving for s is trivial (Gaussian elimination). The error transforms this into the Closest Vector Problem (CVP) on a lattice—exponentially hard for both classical and quantum computers.

ML-KEM (Kyber)

ML-KEM-768 provides NIST Security Level 3 key encapsulation for establishing encrypted channels.

Parameter Set

Parameter ML-KEM-768 Description
Module Rank (k) 3 Number of polynomial vectors
Polynomial Degree (n) 256 Coefficients per polynomial
Modulus (q) 3329 Prime for NTT compatibility
Public Key 1,184 bytes Compressed representation
Ciphertext 1,088 bytes Encrypted shared secret
Secret Key 2,400 bytes Including reject seed

Key Generation

KeyGen()
  1. Generate random seed ρ
  2. Expand ρ via SHAKE-128 to derive matrix A
  3. Sample secret s and error e from CBD(η)
  4. Compute t = As + e
  5. Return (pk = (t, ρ), sk = (s, pk, H(pk), z))

Encapsulation

Encaps(pk)
  1. Generate random message m
  2. Derive (K̄, r) = G(m || H(pk))
  3. Compute ciphertext c = Encrypt(pk, m, r)
  4. Return (c, K = KDF(K̄ || H(c)))

Fujisaki-Okamoto Transform

ML-KEM uses the FO transform to achieve CCA2 security from CPA-secure PKE.

Implicit Rejection

During decapsulation, the implementation re-encrypts the recovered message and compares to the received ciphertext. On mismatch (indicating attack or failure), it returns a pseudorandom key derived from a secret reject seed—never an error code. This prevents timing and validity oracles.

ML-DSA (Dilithium)

ML-DSA-65 provides NIST Security Level 3 signatures using the Fiat-Shamir with Abort paradigm.

Parameter Set

Parameter ML-DSA-65 Description
Module Rank (k, l) (6, 5) Matrix dimensions
Polynomial Degree 256 Coefficients per polynomial
Modulus (q) 8380417 Larger than Kyber for signatures
Public Key 1,952 bytes Compressed t₁
Signature 3,309 bytes (z, h, c̃)
Secret Key 4,032 bytes (ρ, K, tr, s₁, s₂, t₀)

Why Not Falcon?

Falcon
Requires floating-point Gaussian sampling
Side-channel hardening is difficult
Complex constant-time implementation
Smaller signatures but higher risk
Dilithium (ML-DSA)
Integer arithmetic only
Simple CBD sampling
Easier to harden against side-channels
Larger signatures but safer implementation

Rejection Sampling

Naive lattice signatures leak secret key information through the distribution of outputs. ML-DSA uses rejection sampling:

Sign(sk, M)
  1. Compute μ = CRH(tr || M)
  2. Sample masking vector y
  3. Compute w = Ay
  4. Compute challenge c = H(μ || w₁)
  5. Compute z = y + cs₁
  6. If ||z||∞ ≥ γ₁ - β, REJECT and restart
  7. If ||cs₂||∞ ≥ γ₂, REJECT and restart
  8. Return σ = (z, h, c̃)

The rejection loop ensures signatures are statistically independent of the secret key, preventing leakage.

Number Theoretic Transform

Polynomial multiplication is the core operation in lattice cryptography. Naive multiplication is O(n²); NTT reduces this to O(n log n).

Why q = 3329?

The modulus is carefully chosen: 3329 ≡ 1 (mod 512). This means 512th roots of unity exist in Z_q, enabling efficient NTT.

Butterfly Operation

The NTT building block:

a' = a + ζ·b
b' = a - ζ·b

Where ζ is a precomputed twiddle factor (root of unity)

Implementation Requirements

Constant-Time

No branches on secret data. Use bitwise masking instead of conditionals.

Bit Reversal

NTT requires bit-reversed input ordering for in-place computation.

Precomputed Tables

Twiddle factors computed once at startup for maximum performance.

SLH-DSA (SPHINCS+)

SLH-DSA is a stateless hash-based signature scheme serving as Po8's governance fallback.

Security Basis

Unlike lattice schemes, SLH-DSA security depends only on the security of the underlying hash function (SHA-3). No mathematical structure to attack—just hash function preimage resistance.

Trade-offs

Aspect ML-DSA-65 SLH-DSA-128f
Signature Size 3,309 bytes 17,088 bytes
Public Key 1,952 bytes 32 bytes
Sign Time ~0.3 ms ~50 ms
Verify Time ~0.1 ms ~3 ms
Security Assumption MLWE hardness Hash preimage

Use Case

SLH-DSA is too slow for transaction signing but perfect for:

  • Governance key ceremonies
  • Emergency hard fork authorization
  • Root of trust for key rotation
  • Long-term archival signatures

Belt and Suspenders

Po8 uses hybrid key exchange combining classical and post-quantum algorithms.

K_session = HKDF(ECDH(X25519) || Decaps(ML-KEM))

Session key derived from both exchanges

Security Guarantees

If PQC Broken

X25519 maintains security against classical attackers

If ECC Broken

ML-KEM maintains security against quantum attackers

If Implementation Bug

Redundancy provides defense-in-depth

Explore the Implementation

See how these primitives are used in the Po8 node architecture.