mldsa-native is a work-in-progress implementation of the ML-DSA1 post-quantum signature standard. It is a fork of the ML-DSA reference implementation2.
The goal of mldsa-native is to be a secure, fast and portable C90 implementation of ML-DSA, paralleling mlkem-native for ML-KEM.
mldsa-native is work in progress. WE DO NOT CURRENTLY RECOMMEND RELYING ON THIS LIBRARY IN A PRODUCTION ENVIRONMENT OR TO PROTECT ANY SENSITIVE DATA. Once we have the first stable version, this notice will be removed.
# Install base packages
sudo apt-get update
sudo apt-get install make gcc python3 git
# Clone mldsa-native
git clone https://github.com/pq-code-package/mldsa-native.git
cd mldsa-native
# Build and run tests
make build
make test
# The same using `tests`, a convenience wrapper around `make`
./scripts/tests all
# Show all options
./scripts/tests --help
We use the C Bounded Model Checker (CBMC) to prove absence of various classes of undefined behaviour in C, including out of bounds memory accesses and integer overflows. The proofs cover all C code in mldsa/* and mldsa/fips202/* involved in running mldsa-native with its C backend. See proofs/cbmc for details.
All assembly in mldsa-native is constant-time in the sense that it is free of secret-dependent control flow, memory access, and instructions that are commonly variable-time, thwarting most timing side channels. C code is hardened against compiler-introduced timing side channels through suitable barriers and constant-time patterns.
mldsa-native is split into a frontend and two backends for arithmetic and FIPS202 / SHA3. The frontend is fixed, written in C, and covers all routines that are not critical to performance. The backends are flexible, take care of performance-sensitive routines, and can be implemented in C or native code (assembly/intrinsics); see mldsa/native/api.h for the arithmetic backend and mldsa/fips202/native/api.h for the FIPS-202 backend. mldsa-native currently offers backends for C, AArch64, and x86_64 - if you'd like contribute new backends, please reach out or just open a PR.
Once mldsa-native reaches production readiness, you will be able to import mldsa into your project's source tree and build using your preferred build system. The build system provided in this repository is for development purposes only.
mldsa-native relies on and comes with an implementation of FIPS-202[^FIPS202]. If your library has its own FIPS-202 implementation, you can use it instead of the one shipped with mldsa-native.
No. If you want a C-only build, you will be able to omit the native backend directories from your import and configure the build accordingly in your config.h.
No. While we recommend considering formal verification for security-critical applications, mldsa-native will build and run without CBMC. Function contracts and loop invariants will be ignored unless CBMC
is defined during compilation.
Yes. mldsa-native supports all three ML-DSA security levels (ML-DSA-44, ML-DSA-65, ML-DSA-87) as defined in FIPS 204. The security level is a compile-time parameter.
By default, mldsa-native uses the "hedged" signing variant as specified in FIPS 204 Section 3.4, with MLD_RANDOMIZED_SIGNING
enabled in mldsa/config.h. The hedged variant uses both fresh randomness at signing time and precomputed randomness from the private key. This helps mitigate fault injection attacks and side-channel attacks while protecting against potential flaws in the random number generator.
The deterministic variant can be enabled by undefining MLD_RANDOMIZED_SIGNING
, but FIPS 204 warns that this should not be used on platforms where fault injection attacks and side-channel attacks are a concern, as the lack of fresh randomness makes fault attacks more difficult to mitigate.
Yes. mldsa-native supports external mu mode, which allows for pre-hashing of messages before signing. This addresses the pre-hashing capability described in the NIST PQC FAQ3 and detailed in NIST's guidance on FIPS 204 Section 64.
External mu mode enables applications to compute the message digest (mu) externally and provide it to the signing implementation, which is particularly useful for large messages or streaming applications where the entire message cannot be held in memory during signing.
No. mldsa-native does not currently implement HashML-DSA, the hash-based variant of ML-DSA defined in FIPS 204. The current implementation focuses on the standard ML-DSA signature scheme.
Yes, you will be able to add custom backends for ML-DSA native arithmetic and/or for FIPS-202. You will be able to follow the existing backends as templates.
If you think you have found a security bug in mldsa-native, please report the vulnerability through Github's private vulnerability reporting. Please do not create a public GitHub issue.
If you have any other question / non-security related issue / feature request, please open a GitHub issue.
If you want to help us build mldsa-native, please reach out. You can contact the mldsa-native team through the PQCA Discord.
Footnotes
-
National Institute of Standards and Technology: FIPS 204 Module-Lattice-Based Digital Signature Standard, https://csrc.nist.gov/pubs/fips/204/final ↩
-
Bai, Ducas, Kiltz, Lepoint, Lyubashevsky, Schwabe, Seiler, Stehlé: CRYSTALS-Dilithium reference implementation, https://github.com/pq-crystals/dilithium ↩
-
National Institute of Standards and Technology: Post-Quantum Cryptography FAQs, https://csrc.nist.gov/Projects/post-quantum-cryptography/faqs#Rdc7 ↩
-
National Institute of Standards and Technology: FIPS 204 Section 6 Guidance, https://csrc.nist.gov/csrc/media/Projects/post-quantum-cryptography/documents/faq/fips204-sec6-03192025.pdf ↩