BenchmarksStack Ranking
APIsPricingDocsWhite PaperTokenBlogAboutSecurity Demo
Log InGet API Key
Post-Quantum · 23 min read

CRYSTALS-Dilithium:
The Future of Digital Signatures

Everything developers need to know about implementing CRYSTALS-Dilithium quantum-resistant digital signatures. From the lattice math behind Fiat-Shamir with Aborts to NIST FIPS 204 compliance, performance benchmarks, and production Rust code.

FIPS 204
Standard
~240µs
Sign + Verify
128-bit
PQ Security
3
Security Levels

Every time you install a software update, connect to a website over HTTPS, sign a financial transaction, or verify an identity token, digital signatures are doing the work behind the scenes. They are the mathematical proof that a message is authentic—that it came from who it claims to come from, and that it hasn't been tampered with. Without digital signatures, there is no trust on the internet.

For decades, RSA and ECDSA have served as the backbone of digital signature infrastructure. They secure TLS certificate chains, code signing pipelines, blockchain consensus, JWT authentication tokens, and virtually every protocol that requires non-repudiation. But both algorithms rest on mathematical foundations—integer factorization and the elliptic curve discrete logarithm problem—that Shor's algorithm will shatter the moment a cryptographically relevant quantum computer (CRQC) comes online.

CRYSTALS-Dilithium—now standardized as ML-DSA under NIST FIPS 204—is the primary replacement. It is the post-quantum digital signature algorithm that NIST selected as its recommended standard, built on lattice mathematics that no known quantum algorithm can break efficiently. This article covers how it works, why it won, how it performs, and how to implement it.

Key Takeaway

CRYSTALS-Dilithium (ML-DSA) is the NIST-recommended post-quantum digital signature algorithm under FIPS 204. It replaces RSA and ECDSA for all applications requiring quantum resistance. The standards are final, the deadlines are set, and production-grade implementations exist today.

What Digital Signatures Are and Why They Matter

A digital signature is a cryptographic primitive that provides three guarantees:

These properties are fundamental to modern infrastructure. Consider the scope of what depends on them:

Where Digital Signatures Are Used

When Shor's algorithm breaks RSA and ECDSA, every one of these systems becomes vulnerable. An attacker with a CRQC could forge TLS certificates, sign malicious software updates that appear legitimate, authorize fraudulent blockchain transactions, or mint authentication tokens for any identity. The entire trust model of the internet collapses.

This is why post-quantum signature migration is not optional. It is a prerequisite for maintaining digital trust in the quantum era.

How CRYSTALS-Dilithium Works

Dilithium is a lattice-based digital signature scheme that uses the Fiat-Shamir with Aborts paradigm, with its security derived from the hardness of the Module Learning With Errors (MLWE) problem. Let's unpack each of these components.

Module Learning With Errors (MLWE)

The security of Dilithium rests on the difficulty of the MLWE problem. In simplified terms, given a system of "noisy" linear equations over a polynomial ring, it is computationally infeasible to recover the secret values—even with a quantum computer.

More precisely, MLWE works over the polynomial ring R_q = Z_q[X]/(X^n + 1), where n = 256 and q = 8380417 (a specific prime chosen for NTT-friendliness). The secret key consists of short polynomials (with small coefficients), and the public key is constructed as t = A * s1 + s2, where A is a public random matrix, s1 is the secret signing key, and s2 is a secret error term. Recovering s1 from A and t is the MLWE problem—and no known quantum algorithm solves it efficiently.

Why Lattices Are Quantum-Safe

Shor's algorithm exploits the hidden subgroup structure in factoring and discrete logarithm problems. Lattice problems like MLWE have no such structure. The best known quantum algorithms for lattice problems (based on quantum variants of BKZ) provide only a modest polynomial speedup over classical algorithms—nowhere near the exponential speedup Shor provides against RSA/ECDSA. This is why the entire NIST PQC portfolio is dominated by lattice-based constructions.

The Fiat-Shamir with Aborts Paradigm

Dilithium's signing process is based on the Fiat-Shamir transform applied to an identification scheme, but with a critical twist: the abort mechanism. Here is how the three core operations work:

Key Generation

  1. Generate a random seed and expand it into a public matrix A (a k x l matrix of polynomials)
  2. Sample short secret vectors s1 (length l) and s2 (length k) with coefficients bounded by η
  3. Compute t = A * s1 + s2
  4. The public key is (A, t); the private key is (A, t, s1, s2)

Signing (with Aborts)

  1. Sample a random masking vector y with coefficients bounded by γ1
  2. Compute w = A * y and extract its high-order bits w1
  3. Compute the challenge hash: c = H(w1 || message)
  4. Compute the response: z = y + c * s1
  5. Rejection check: If z has any coefficient with absolute value ≥ γ1 - β, ABORT and restart from step 1
  6. Second check: Verify that the low-order bits of A*z - c*t don't exceed a bound. If they do, ABORT and restart.
  7. If both checks pass, output signature (z, c)

Verification

  1. Check that all coefficients of z are within bounds
  2. Compute w1' = HighBits(A*z - c*t)
  3. Verify that H(w1' || message) = c
Why the Abort Mechanism Matters

Without rejection sampling (the abort step), the distribution of signatures would leak information about the secret key s1. Each signature z = y + c*s1 is shifted by c*s1, which would gradually reveal s1 over many signatures. The abort mechanism ensures that only signatures where z follows a near-uniform distribution are output—completely masking the secret key. On average, signing requires 4–7 iterations before producing a valid signature, but each iteration is fast (microseconds), so the overhead is minimal.

Security Levels: ML-DSA-44, ML-DSA-65, ML-DSA-87

Dilithium defines three parameter sets, each targeting a different NIST security level. Under the FIPS 204 standard, these are designated ML-DSA-44, ML-DSA-65, and ML-DSA-87 (the numbers refer to the (k, l) matrix dimensions).

Parameter ML-DSA-44 ML-DSA-65 ML-DSA-87
NIST Security Level 2 3 5
Classical Equivalent ~AES-128 ~AES-192 ~AES-256
Matrix (k × l) 4 × 4 6 × 5 8 × 7
Public Key 1,312 bytes 1,952 bytes 2,592 bytes
Signature Size 2,420 bytes 3,293 bytes 4,595 bytes
Secret Key 2,560 bytes 4,032 bytes 4,896 bytes
η (secret bound) 2 4 2
γ1 (masking range) 217 219 219
CNSA 2.0 Compliant No Acceptable Required

ML-DSA-65 (Dilithium3) is the recommended parameter set for most applications. It provides NIST Security Level 3 (~AES-192 equivalent) with a good balance of key size, signature size, and performance. For national security systems, ML-DSA-87 (Dilithium5) is required by CNSA 2.0.

Performance: Dilithium vs. RSA vs. ECDSA

One of Dilithium's greatest strengths is its performance. Unlike some post-quantum candidates that impose severe computational overhead, Dilithium is faster than RSA for signing and verification, and competitive with ECDSA in most operations.

Key Size and Signature Size Comparison

Algorithm Security Public Key Signature Secret Key
RSA-2048 ~112-bit 256 B 256 B ~1,200 B
RSA-3072 ~128-bit 384 B 384 B ~1,700 B
ECDSA P-256 ~128-bit 64 B 64 B 32 B
Ed25519 ~128-bit 32 B 64 B 32 B
ML-DSA-44 ~128-bit PQ 1,312 B 2,420 B 2,560 B
ML-DSA-65 ~192-bit PQ 1,952 B 3,293 B 4,032 B
ML-DSA-87 ~256-bit PQ 2,592 B 4,595 B 4,896 B

Yes, Dilithium keys and signatures are larger than classical algorithms. An ML-DSA-65 public key is 1,952 bytes versus 64 bytes for ECDSA P-256—a 30x increase. But 1,952 bytes is still small in absolute terms. For context, a single TCP packet can carry up to 1,460 bytes of payload, so a Dilithium public key fits in two packets. The signature at 3,293 bytes fits in three. For most applications (API authentication, code signing, certificate chains), this overhead is negligible.

Where Size Matters

Bandwidth-constrained environments are the exception. IoT devices with limited packet sizes, blockchain transactions where every byte costs gas, and DNS-based certificate distribution (DANE) may need careful consideration. For these use cases, NIST has standardized SLH-DSA (FIPS 205, hash-based) and is drafting FN-DSA (FIPS 206, from FALCON) which offers smaller signatures at the cost of implementation complexity.

Speed Benchmarks

On modern hardware, Dilithium is remarkably fast. Our February 2026 benchmarks on AWS Graviton4 (c8g.metal-48xl, 192 vCPUs, Neoverse V2, ARM NEON) show:

H33 Production Benchmarks — ML-DSA-65 (Graviton4, Feb 2026)

Key Generation
36.6 µs
Signing
45.0 µs
Verification
36.9 µs
Sign + Verify
~82 µs
Pool KeyGen
0.35 µs
RSA-2048 Sign
~1,500 µs
RSA-2048 Verify
~25 µs
ECDSA P-256 Sign
~60 µs
ECDSA P-256 Verify
~100 µs

Dilithium signing at 45µs is 33x faster than RSA-2048 signing (~1,500µs). Dilithium verification at 36.9µs is competitive with RSA verification (~25µs) and significantly faster than ECDSA verification (~100µs). With our key pool architecture (pre-generated keys), we achieve an effective keygen cost of just 0.35µs, enabling 2.86M signature operations per second on a single 96-worker node.

NIST FIPS 204: From Dilithium to ML-DSA

Understanding the naming history helps avoid confusion in documentation and procurement:

2017
CRYSTALS-Dilithium submitted to NIST PQC competition by a team from CWI Amsterdam, ENS Lyon, IBM Research, and several universities. Named after the fictional Star Trek material.
2020
Round 3 finalist—Dilithium advanced as one of three signature scheme finalists (alongside FALCON and Rainbow).
July 2022
NIST selects Dilithium as the primary post-quantum digital signature standard. Rainbow was broken; FALCON advanced as a secondary standard.
August 2024
FIPS 204 published—Dilithium is standardized under the name ML-DSA (Module-Lattice Digital Signature Algorithm). Three parameter sets: ML-DSA-44, ML-DSA-65, ML-DSA-87.
November 2024
NIST IR 8547—transition roadmap published. RSA and ECDSA deprecated after 2030, disallowed in federal systems after 2035.
~2026
FIPS 206 (FN-DSA) expected—FALCON-based alternative with smaller signatures but more complex implementation.

The key point: CRYSTALS-Dilithium and ML-DSA are the same algorithm. FIPS 204 made minor tweaks to the specification (deterministic vs. hedged signing modes, domain separation), but the core math is identical. If you see "Dilithium3" in code or documentation, it corresponds to ML-DSA-65.

Why Dilithium Won Over FALCON

NIST had two lattice-based signature finalists: Dilithium and FALCON. Both are quantum-resistant. FALCON actually produces smaller signatures (666 bytes for FALCON-512 vs. 2,420 bytes for ML-DSA-44 at comparable security). So why did NIST choose Dilithium as the primary standard?

Criterion Dilithium (ML-DSA) FALCON (FN-DSA)
Signature Size 2,420–4,595 B 666–1,280 B
Public Key Size 1,312–2,592 B 897–1,793 B
Implementation Simplicity Simple (NTT + rejection sampling) Complex (requires discrete Gaussian sampling over NTRU lattices)
Constant-Time Feasibility Straightforward Extremely difficult (floating-point Gaussian sampling is timing-dependent)
Floating-Point Dependency None Requires double-precision FP for Gaussian sampling
Side-Channel Risk Low (integer arithmetic throughout) High (FP timing, cache-line leaks in tree sampling)
Embedded/Constrained Devices Portable (no FP required) Problematic (many embedded platforms lack FP or have non-IEEE FP)
Signing Speed Fast (~45 µs) Fast (~40 µs)

The decisive factors were implementation simplicity and constant-time safety:

NIST's Assessment

"CRYSTALS-Dilithium is recommended as the primary algorithm for digital signatures due to its strong security, excellent performance, and relative ease of implementation. Its use of Module-LWE aligns well with ML-KEM (FIPS 203), allowing shared infrastructure for both signatures and key encapsulation."

FALCON will still be standardized as FN-DSA (FIPS 206, expected ~2026) for applications where signature size is the dominant constraint. But for general-purpose use, Dilithium is the answer.

Use Cases: Where to Deploy ML-DSA

Dilithium is a drop-in replacement for RSA and ECDSA signatures in virtually every context. Here are the primary deployment scenarios:

TLS Certificates and PKI

Certificate authorities will need to issue ML-DSA certificates for TLS. The larger certificate size (public key + signature in the cert chain) adds a few kilobytes to the TLS handshake. Measurements show this adds less than 1ms of additional latency on typical connections. Chrome and Firefox already support ML-DSA in experimental builds, and the IETF has published drafts for ML-DSA in X.509 certificates.

Code Signing

Software publishers sign binaries to prove authenticity. ML-DSA replaces RSA/ECDSA in code signing pipelines with minimal changes. The 3,293-byte signature (ML-DSA-65) is negligible compared to typical binary sizes. Microsoft, Apple, and Linux distributions are all working on PQC code signing support.

Blockchain and Cryptocurrency

Blockchain consensus mechanisms rely on signatures for transaction authorization. The larger signature sizes increase on-chain storage costs, but several chains (Ethereum, Algorand) are actively researching ML-DSA integration. For blockchains where signature size is critical, FN-DSA (FALCON) may be preferred due to its 666-byte signatures.

Authentication Tokens (JWT, SAML)

JSON Web Tokens signed with ML-DSA (using the ML-DSA-65 algorithm identifier) are a direct replacement for RS256 or ES256. The token size increases by ~3KB, which is acceptable for API authentication but may matter for cookie-based sessions where header size is constrained.

Attestation and Zero-Knowledge Proofs

In H33's production stack, Dilithium signs attestation digests that bind FHE computation results to a verifiable proof. A single Dilithium sign+verify cycle (~240µs including SHA3 digest computation) attests an entire batch of 32 biometric authentications, providing cryptographic proof that the computation was performed correctly without revealing any biometric data.

CNSA 2.0 Deadlines for Signature Migration

The NSA's Commercial National Security Algorithm Suite 2.0 (CNSA 2.0) sets hard deadlines for migrating away from classical signatures. If your organization sells to the U.S. government or handles national security data, these deadlines are contractual requirements.

Category Prefer ML-DSA By Exclusive ML-DSA By Required Level
Software & firmware signing 2025 2030 ML-DSA-87
Web servers, browsers, cloud 2025 2033 ML-DSA-87
Traditional networking (VPN, routers) 2026 2030 ML-DSA-87
Operating systems 2027 2033 ML-DSA-87
Constrained devices, large PKI 2030 2033 ML-DSA-87
CNSA 2.0 Requires ML-DSA-87

For national security systems, CNSA 2.0 mandates ML-DSA-87 (Dilithium5, Security Level 5)—not ML-DSA-65. This is a higher bar than NIST's general recommendation. If you are building for government or defense customers, plan for ML-DSA-87 from the start. Retrofitting from ML-DSA-65 to ML-DSA-87 later requires regenerating all keys and re-signing all existing artifacts.

Beyond CNSA 2.0, NIST IR 8547 (November 2024) sets the broader federal timeline: RSA and ECDSA deprecated after 2030, disallowed after 2035. These deadlines apply to all federal systems, not just national security systems. If your product touches federal infrastructure in any capacity, the clock is already ticking.

H33's Dilithium Implementation

H33 uses CRYSTALS-Dilithium (ML-DSA-65) as the attestation layer in its production authentication stack. Every biometric authentication request is attested with a Dilithium signature, providing post-quantum non-repudiation for the entire computation.

Production Architecture

H33 Single API Call — Signature Component

  1. FHE Batch—BFV inner product over 32 encrypted biometric templates (~1,109µs)
  2. ZKP—STARK lookup proof of computation integrity (~0.067µs)
  3. Attestation—SHA3-256 digest of results + 1 Dilithium sign+verify (~240µs)
~1,615 µs
Total (32 users)
~50 µs
Per Authentication
2.17M/sec
Sustained Throughput

Batch Attestation: 31x Efficiency Gain

A naive approach would sign each of the 32 user results individually, requiring 32 Dilithium sign+verify cycles (32 × 82µs = 2,624µs). Instead, H33 uses batch attestation: the SHA3-256 digest covers the entire batch of 32 results, and a single Dilithium signature attests all of them at once. This is a 31x reduction in attestation overhead (240µs vs. 2,624µs) while maintaining the same cryptographic guarantees—if any result in the batch is tampered with, the digest changes and the signature fails verification.

Rust Code Example: Sign and Verify with Dilithium

Here is a complete, production-grade example of Dilithium signing and verification in Rust, similar to the pattern used in H33's attestation pipeline:

Rust dilithium_sign_verify.rs
use sha3::{Sha3_256, Digest};
use pqcrypto_dilithium::dilithium3;
use pqcrypto_traits::sign::{PublicKey, SecretKey, SignedMessage, DetachedSignature};

/// Generate a Dilithium3 (ML-DSA-65) key pair
fn generate_keypair() -> (dilithium3::PublicKey, dilithium3::SecretKey) {
    dilithium3::keypair()
}

/// Sign arbitrary data with SHA3-256 pre-hashing + Dilithium
fn sign_data(data: &[u8], sk: &dilithium3::SecretKey) -> dilithium3::DetachedSignature {
    // Pre-hash with SHA3-256 for domain separation
    let mut hasher = Sha3_256::new();
    hasher.update(data);
    let digest = hasher.finalize();

    // Sign the digest (NOT the raw data) — standard practice
    dilithium3::detached_sign(&digest, sk)
}

/// Verify signature against data + public key
fn verify_signature(
    data: &[u8],
    sig: &dilithium3::DetachedSignature,
    pk: &dilithium3::PublicKey,
) -> bool {
    let mut hasher = Sha3_256::new();
    hasher.update(data);
    let digest = hasher.finalize();

    dilithium3::verify_detached_signature(sig, &digest, pk).is_ok()
}

/// Batch attestation: sign a batch of results with one signature
fn batch_attest(
    results: &[AuthResult],
    sk: &dilithium3::SecretKey,
) -> dilithium3::DetachedSignature {
    let mut hasher = Sha3_256::new();
    for result in results {
        hasher.update(&result.user_id.to_le_bytes());
        hasher.update(&[result.match_result as u8]);
        hasher.update(&result.timestamp.to_le_bytes());
    }
    let batch_digest = hasher.finalize();
    dilithium3::detached_sign(&batch_digest, sk)
}

fn main() {
    // Key generation (~36.6µs on Graviton4)
    let (pk, sk) = generate_keypair();

    // Sign some data (~45µs on Graviton4)
    let message = b"Transfer $1,000 from account A to B";
    let signature = sign_data(message, &sk);

    // Verify (~36.9µs on Graviton4)
    let valid = verify_signature(message, &signature, &pk);
    assert!(valid, "Signature must verify");

    // Tampered message fails verification
    let tampered = b"Transfer $1,000,000 from account A to B";
    let invalid = verify_signature(tampered, &signature, &pk);
    assert!(!invalid, "Tampered message must fail");

    println!("Dilithium sign+verify: OK");
    println!("Public key:  {} bytes", pk.as_bytes().len());
    println!("Signature:   {} bytes", sig.as_bytes().len());
}

Implementation Considerations

Deploying Dilithium in production requires attention to several practical concerns beyond the core algorithm.

Constant-Time Implementation

All Dilithium operations must be implemented in constant time to prevent timing side-channel attacks. This means:

The good news: Dilithium is much easier to implement in constant time than FALCON, because it uses only integer arithmetic. No floating-point, no discrete Gaussian sampling, no tree-based secret operations. This was a major factor in NIST's selection.

Random Number Generation

Dilithium requires high-quality randomness in two places: key generation (sampling s1, s2) and signing (sampling the masking vector y). Using a weak RNG is catastrophic—if an attacker can predict y, they can recover the secret key from a single signature.

Critical: RNG Quality

Always use a cryptographically secure RNG (e.g., /dev/urandom, getrandom(), or OsRng in Rust). FIPS 204 also supports hedged signing (combining randomness with the secret key and message hash) to provide resilience against RNG failures. In production, always use hedged mode.

Key Management

Dilithium key management follows the same principles as classical signature schemes, with a few differences:

Hybrid Signatures: The Migration Bridge

A hybrid signature combines a classical signature (RSA or ECDSA) with a post-quantum signature (ML-DSA) on the same message. The verifier checks both. This provides two guarantees:

Hybrid signatures are recommended by NIST, CNSA 2.0, and most migration guides as the transition approach. The overhead is manageable: a hybrid ML-DSA-65 + ECDSA P-256 signature is ~3,357 bytes (3,293 + 64), and verification takes ~137µs (36.9 + ~100).

Rust hybrid_signature.rs
/// Hybrid signature: ML-DSA-65 + ECDSA P-256
/// Both must verify for the signature to be accepted
pub struct HybridSignature {
    dilithium_sig: dilithium3::DetachedSignature,
    ecdsa_sig: ecdsa::Signature,
}

pub fn hybrid_sign(
    data: &[u8],
    dil_sk: &dilithium3::SecretKey,
    ec_sk: &ecdsa::SigningKey,
) -> HybridSignature {
    let digest = Sha3_256::digest(data);
    HybridSignature {
        dilithium_sig: dilithium3::detached_sign(&digest, dil_sk),
        ecdsa_sig: ec_sk.sign(&digest),
    }
}

pub fn hybrid_verify(
    data: &[u8],
    sig: &HybridSignature,
    dil_pk: &dilithium3::PublicKey,
    ec_pk: &ecdsa::VerifyingKey,
) -> bool {
    let digest = Sha3_256::digest(data);

    // BOTH signatures must verify
    let dil_ok = dilithium3::verify_detached_signature(
        &sig.dilithium_sig, &digest, dil_pk
    ).is_ok();

    let ec_ok = ec_pk.verify(&digest, &sig.ecdsa_sig).is_ok();

    dil_ok && ec_ok
}

The Complete PQC Signature Landscape

Dilithium is not the only post-quantum signature algorithm. Understanding the full landscape helps with architectural decisions:

Standard Algorithm Family Signature PK Size Status Best For
FIPS 204 ML-DSA (Dilithium) Lattice (MLWE) 2,420–4,595 B 1,312–2,592 B Final General purpose
FIPS 205 SLH-DSA (SPHINCS+) Hash-based 7,856–49,856 B 32–64 B Final Conservative / tiny PK
FIPS 206 FN-DSA (FALCON) Lattice (NTRU) 666–1,280 B 897–1,793 B Draft ~2026 Small signatures

SLH-DSA (FIPS 205) is the "conservative" choice. Its security relies only on the properties of hash functions (SHA-256/SHAKE), making it theoretically the safest bet if lattice problems turn out to be easier than expected. The tradeoff: signatures are enormous (7–50KB) and signing is slow. Use it for root-of-trust applications (root CA certificates, firmware signing keys) where you sign rarely and verify occasionally.

FN-DSA (FIPS 206) from FALCON offers the smallest signatures (666 bytes) at the cost of implementation complexity. Once standardized, it will be preferred for blockchain transactions and other bandwidth-critical applications.

ML-DSA (FIPS 204) from Dilithium is the default. If you're unsure which to use, use Dilithium.

Common Implementation Pitfalls

Based on H33's production experience and published vulnerability research, here are the most common mistakes when implementing Dilithium:

Pitfalls to Avoid

  1. Using deterministic signing without hedging. Pure deterministic signing (deriving y from the message + secret key with no randomness) is vulnerable to fault attacks. If an attacker can induce a computational fault during signing, they can recover the secret key from two faulty signatures of the same message. FIPS 204 supports hedged mode (randomness + deterministic component) for exactly this reason.
  2. Leaking the rejection count. The number of abort-and-retry iterations during signing must not be observable (via timing, power consumption, or electromagnetic emanations). A side-channel that reveals how many iterations occurred leaks information about the secret key.
  3. Reusing nonces / masking vectors. If the same masking vector y is used for two different messages, the secret key can be trivially recovered (similar to the ECDSA nonce-reuse attack that broke the PlayStation 3).
  4. Not validating public key format. Malformed public keys can cause undefined behavior in some implementations. Always validate that deserialized public keys have correct dimensions and coefficient bounds before use.
  5. Ignoring algorithm agility. Hardcoding ML-DSA-65 everywhere makes future migration to ML-DSA-87 (or a different algorithm entirely) painful. Design your systems with algorithm identifiers and pluggable signature backends from the start.

Migration Roadmap: From RSA/ECDSA to ML-DSA

Migrating a production system from classical signatures to Dilithium is a multi-phase effort. Here is the recommended approach:

Phase 1: Inventory and Assessment (Weeks 1–4)

Phase 2: Hybrid Deployment (Months 2–6)

Phase 3: PQ-Primary (Months 6–12)

Phase 4: PQ-Exclusive (Month 12+)

Start with Key Exchange, Not Signatures

If you can only do one thing today, prioritize post-quantum key exchange (ML-KEM / FIPS 203) over post-quantum signatures. Key exchange protects data confidentiality—the thing HNDL attacks exploit. Signature migration protects authentication integrity, which is critical but not vulnerable to retroactive attacks in the same way. Both are necessary, but key exchange has a tighter deadline.

Frequently Asked Questions

Is Dilithium the same as ML-DSA?

Yes. CRYSTALS-Dilithium was renamed to ML-DSA (Module-Lattice Digital Signature Algorithm) during NIST's FIPS 204 standardization. The core algorithm is identical. Minor changes in the standard include updated domain separation labels and support for both deterministic and hedged signing modes.

Which parameter set should I use?

ML-DSA-65 for most applications. It provides NIST Security Level 3 (comparable to AES-192) with a good performance-size tradeoff. Use ML-DSA-87 if you need CNSA 2.0 compliance or Security Level 5. Use ML-DSA-44 only for highly constrained environments where you've confirmed Level 2 security meets your requirements.

How do Dilithium signatures compare in size to RSA?

ML-DSA-65 signatures are 3,293 bytes versus 256 bytes for RSA-2048—about 13x larger. But RSA-2048 is not quantum-safe, and comparing to the quantum-equivalent RSA-15360 (if such a thing existed), Dilithium signatures would actually be smaller. In practice, 3,293 bytes is a non-issue for most applications.

Can existing HSMs support Dilithium?

Major HSM vendors (Thales, Entrust, AWS CloudHSM, Azure Dedicated HSM) are adding ML-DSA support. Some already offer firmware updates with PQC algorithms. Check with your vendor for the current status. For software-based key management, production-grade Dilithium implementations exist in liboqs, pqcrypto (Rust), bouncy-castle (Java), and OpenSSL 3.x (via oqs-provider).

What about performance on constrained devices?

Dilithium is designed to be efficient on a wide range of hardware. Reference benchmarks on ARM Cortex-M4 (a common microcontroller) show signing in ~2ms and verification in ~1ms. These numbers are well within the requirements for IoT authentication, smart cards, and embedded systems.

The Bottom Line

CRYSTALS-Dilithium (ML-DSA, FIPS 204) is the post-quantum digital signature standard. The algorithm is mature, the standard is final, production implementations exist in every major language, and the regulatory deadlines are set. There is no ambiguity about what to do—only about when to start.

The performance is excellent: 45µs signing and 37µs verification on modern hardware, 33x faster than RSA signing, competitive with ECDSA. The key and signature sizes are larger than classical algorithms but manageable for virtually all applications. The security is well-understood, resting on the Module-LWE problem that has withstood decades of cryptanalytic scrutiny with no efficient quantum attack known.

H33's production stack demonstrates what a fully post-quantum signature deployment looks like: ML-DSA-65 attestation at ~240µs per batch, 2.17M authenticated operations per second, every signature quantum-resistant by construction. The technology works. The only remaining variable is organizational will.

If you are still signing with RSA or ECDSA, your clock started when FIPS 204 was published in August 2024. The CNSA 2.0 "prefer by" deadline for software signing was 2025. The "exclusive use" deadline is 2030. The quantum computer that will break your classical signatures is a matter of when, not if.

Start with hybrid signatures today. Move to PQ-exclusive as your ecosystem supports it. The math is clear, the standards are final, and the tools are ready.


H33 provides post-quantum authentication infrastructure with FHE biometric processing (BFV lattice-based), ML-DSA digital signatures, and ML-KEM key exchange—all in a single API call at sub-millisecond latency. Every component in the stack is quantum-resistant by construction, not by policy.

Build With Post-Quantum Security

Enterprise-grade FHE, ZKP, and post-quantum cryptography. One API call. Sub-millisecond latency.

Get Free API Key → Read the Docs
Free tier · 10,000 API calls/month · No credit card required
Verify It Yourself