A high-performance C++17 implementation of ML-DSA (Module-Lattice-Based Digital Signature Algorithm), standardized as FIPS 204, based on the CRYSTALS-Dilithium post-quantum cryptography scheme.
- Post-Quantum Secure: Quantum-resistant digital signatures based on lattice problems
- FIPS 204 Compliant: Implements the official NIST standard
- Three Parameter Sets: ML-DSA-44 (security level 2), ML-DSA-65 (security level 3), ML-DSA-87 (security level 5)
- Zero Heap Allocation: Stack-only memory model suitable for bare-metal and constrained environments
- No Runtime Exceptions: Compiled with
-fno-exceptionsfor predictable behavior - Minimal Dependencies: Uses only C++17 standard library headers (
<cstdint>,<cstddef>,<cstring>) - RISC-V Ready: Designed with bare-metal targets in mind; includes on-demand matrix optimization mode
# Standard build
cmake -B build -S .
cmake --build build
# With on-demand matrix optimization (reduces stack usage)
cmake -B build -S . -DDLDSA_ONDEMAND_MATRIX=ON
cmake --build build
# Without tests
cmake -B build -S . -DDLDSA_BUILD_TESTS=OFF
cmake --build build# Run all tests
ctest --test-dir build --output-on-failure
# Run a specific test suite
./build/tests/test_sign
# Run tests matching a pattern
./build/tests/test_sign --gtest_filter="SignVerify.ML_DSA_44*"- Algorithm Overview — In-depth explanation of the ML-DSA algorithm, its mathematical foundations, and security properties
- API Reference — Complete documentation of the C++ API, parameter sets, and usage patterns
- Quick Start Guide — Practical examples and getting started instructions
- PLAN.md — Architecture and implementation plan
- Optimization Notes — Details on memory optimization techniques
#include "dldsa/sign.hpp"
using namespace dldsa;
// Example RNG (in production, use a cryptographically secure source)
void secure_rng(uint8_t* out, size_t len, void* ctx) {
// Fill 'out' with 'len' cryptographically secure random bytes
}
// Allocate keys on the stack (no heap allocation)
PublicKey44 pk;
SecretKey44 sk;
MLDSA44::keygen(pk, sk, secure_rng, nullptr);
// Sign a message
uint8_t msg[] = "Hello, post-quantum world!";
Signature44 sig;
SignResult res = MLDSA44::sign(sig, msg, sizeof(msg), nullptr, 0, sk, secure_rng, nullptr);
// res.code == 0 on success; res.siglen holds the actual signature length
// Verify a signature
int result = MLDSA44::verify(sig, msg, sizeof(msg), nullptr, 0, pk);
// result == 0 means valid, result == -2 means invalidThe raw-pointer overloads (keygen(uint8_t* pk, ...), sign(uint8_t* sig, size_t* siglen, ...),
verify(const uint8_t* sig, size_t siglen, ...)) are still available but marked [[deprecated]].
| Set | Security Level | PK Size | SK Size | Signature Size | Latency |
|---|---|---|---|---|---|
| ML-DSA-44 | NIST Level 2 | 1312 B | 2560 B | 2420 B | ~300 µs |
| ML-DSA-65 | NIST Level 3 | 1952 B | 4032 B | 3309 B | ~600 µs |
| ML-DSA-87 | NIST Level 5 | 2592 B | 4896 B | 4627 B | ~1 ms |
- Namespace: All code lives in
dldsa::namespace - Top-Level API:
include/dldsa/sign.hpp—MLDSA<Params>template withkeygen,sign,verify; definesSignResult - Key Types:
include/dldsa/keys.hpp—PublicKey<Params>,SecretKey<Params>,Signature<Params>and per-set aliases (PublicKey44/65/87, etc.) - Parameters:
include/dldsa/params.hpp—ML_DSA_44,ML_DSA_65,ML_DSA_87struct definitions - Core Types:
include/dldsa/types.hpp—Poly,PolyVec<N>, and global constants - RNG:
include/dldsa/rng.hpp— Pluggable RNG interface for maximum flexibility
All functions return int status codes:
0— Success-1— Invalid argument (null pointer, bad buffer lengths)-2— Verification failed (signature does not match message/public key)-3— Signature generation failed (rejection loop limit exceeded)
- FIPS 204: Module-Lattice-Based Digital Signature Standard
- CRYSTALS-Dilithium: Original academic design (Ducas et al.)
- Hedged Signing: Supports optional randomization in signing for additional security
- Compiler: GCC with
-Wall -Wextra -Wpedantic(no warnings allowed) - Testing: Google Test v1.14.0
- Build System: CMake 3.14+
- Target: C++17 with
-fno-exceptionsand-fno-rtti
TBD