sp1-ntt-gadget

Crates.iosp1-ntt-gadget
lib.rssp1-ntt-gadget
version0.1.0
created_at2025-12-08 05:58:11.106027+00
updated_at2025-12-08 05:58:11.106027+00
descriptionNTT/INTT Custom Gadget for Dilithium (ML-DSA-65) verification in SP1 zkVM with 60-bit soundness PIC
homepagehttps://github.com/kota1026/pq-wallet-sp1-ntt-gadget-
repositoryhttps://github.com/kota1026/pq-wallet-sp1-ntt-gadget-
max_upload_size
id1972779
size261,789
(kota1026)

documentation

https://docs.rs/sp1-ntt-gadget

README

sp1-ntt-gadget

Crates.io Documentation License: MIT

High-performance NTT/INTT implementation for Dilithium (ML-DSA-65) verification in SP1 zkVM with 60-bit soundness.

Features

  • 🔐 CRYSTALS-Dilithium Compatible: 100% compatible with FIPS 204 (ML-DSA-65) parameters
  • Optimized Montgomery Arithmetic: Constant-time operations for side-channel resistance
  • 🛡️ 60-bit Soundness: Polynomial Identity Check (PIC) with Fiat-Shamir challenges
  • 🔧 SP1 zkVM Ready: Native integration with SP1 precompile syscalls
  • 📦 no_std Compatible: Works in embedded and zkVM environments

Quick Start

Add to your Cargo.toml:

[dependencies]
sp1-ntt-gadget = "0.1"

Basic NTT/INTT

use sp1_ntt_gadget::{ntt::forward::ntt, ntt::inverse::intt, params::N};

fn main() {
    // 256 coefficients in Z_q (q = 8,380,417)
    let mut coeffs = [0u32; N];
    coeffs[0] = 42;
    coeffs[1] = 59;

    // Forward NTT
    let original = coeffs;
    ntt(&mut coeffs);

    // Inverse NTT (roundtrip)
    intt(&mut coeffs);

    assert_eq!(coeffs, original);
}

Verified NTT (with PIC)

use sp1_ntt_gadget::{
    ntt::forward::ntt,
    pic::verifier::verify_ntt_simple,
    params::N,
};

fn main() {
    let mut coeffs = [0u32; N];
    for i in 0..N {
        coeffs[i] = (i as u32 * 12345) % 8_380_417;
    }

    let original = coeffs;
    ntt(&mut coeffs);

    // Verify NTT correctness (60-bit soundness)
    let context = b"my-application-context";
    assert!(verify_ntt_simple(&original, &coeffs, context).is_ok());
}

SP1 Precompile Integration

use sp1_ntt_gadget::precompile::sp1_hook::{
    NttInput, execute_ntt_with_verification
};

fn main() {
    let input = NttInput {
        coefficients: [42u32; 256],
        context: *b"sp1-ntt-gadget-context-v1\0\0\0\0\0\0\0",
    };

    let output = execute_ntt_with_verification(&input);

    assert!(output.verified);
    println!("NTT output: {:?}", &output.ntt_coefficients[..4]);
}

Parameters

Parameter Value Description
Q 8,380,417 Dilithium prime (q ≡ 1 mod 512)
N 256 Polynomial degree
NUM_CHALLENGES 4 PIC challenges (60-bit soundness)

Modules

Module Description
ntt::forward Forward NTT (Cooley-Tukey)
ntt::inverse Inverse NTT (Gentleman-Sande)
ntt::montgomery Montgomery arithmetic
pic::challenge Fiat-Shamir challenge derivation
pic::verifier NTT verification with PIC
validation::input Coefficient range validation
precompile::sp1_hook SP1 syscall integration

Performance

Native Benchmarks (Apple M1)

Operation Time
NTT (forward) ~1.3 µs
INTT (inverse) ~1.9 µs
Verified NTT ~5.1 µs

SP1 Network Proof (Groth16)

Metric Value
Proof Size 260 bytes
Proof Time ~22 seconds
On-chain Verifiable ✅ Yes

Testing

# Run all tests (104 tests)
cargo test

# Run with specific test suite
cargo test --test ntt_gate1      # Gate 1: NTT correctness
cargo test --test pic_gate2      # Gate 2: PIC soundness
cargo test --test fuzz_ntt       # Fuzzing (100k+ iterations)

Security

  • Soundness: 60-bit (NUM_CHALLENGES=4, each with ~15-bit security)
  • Side-channel Resistance: Constant-time Montgomery arithmetic
  • Tested: 132,731+ fuzzing iterations, 104 unit tests

References

License

MIT License - see LICENSE-MIT for details.

Contributing

Contributions welcome! Please open an issue or PR.


Part of the PQ Wallet project - Post-Quantum Cryptography for Web3

Commit count: 0

cargo fmt