Skip to main content

Crate bouncycastle_mldsa

Crate bouncycastle_mldsa 

Source
Expand description

This crate implements the Module Lattice Digital Signature Algorithm (ML-DSA) as per FIPS 204.

§Usage

This crate has been designed to serve a wide range of use cases, from people dabbling in cryptography for the first time, to cryptographic protocol designers who need access to the internal and advanced functionality of the ML-DSA algorithm, to embedded systems developers who want access to memory and performance optimized functions.

This page gives examples of simple usage for generating keys and signatures, and verifying signatures.

More examples on advanced usage can be found on the mldsa and hash_mldsa pages.

§Generating Keys

use bouncycastle_mldsa::MLDSA65;
use bouncycastle_core::traits::Signature;

let (pk, sk) = MLDSA65::keygen().unwrap();

That’s it. That will use the library’s default OS-backend RNG.

Commonly with the ML-DSA algorithm, a 32-byte seed is used as the private key, and expanded into a full private key as needed. This is offered through the library’s KeyMaterialTrait object:

use bouncycastle_core::key_material::{KeyMaterial256, KeyType, KeyMaterialTrait};
use bouncycastle_mldsa::{MLDSA65, MLDSATrait};
use bouncycastle_hex as hex;

let seed = KeyMaterial256::from_bytes_as_type(
    &hex::decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f").unwrap(),
    KeyType::Seed,
).unwrap();

let (pk, sk) = MLDSA65::keygen_from_seed(&seed).unwrap();

See MLDSATrait and MLDSATrait::sign_mu_deterministic_from_seed for an API flow that uses a merged keygen-and-sign function to provide improved speed and memory performance compared with making separate calls to MLDSATrait::keygen_from_seed followed by Signature::sign.

§Generating and Verifying Signatures

use bouncycastle_mldsa::{MLDSA65, MLDSATrait};
use bouncycastle_core::traits::Signature;
use bouncycastle_core::errors::SignatureError;

let msg = b"The quick brown fox";

let (pk, sk) = MLDSA65::keygen().unwrap();

let sig = MLDSA65::sign(&sk, msg, None).unwrap();
// This is the signature value that you can save to a file or whatever you need.

match MLDSA65::verify(&pk, msg, None, &sig) {
    Ok(()) => println!("Signature is valid!"),
    Err(SignatureError::SignatureVerificationFailed) => println!("Signature is invalid!"),
    Err(e) => panic!("Something else went wrong: {:?}", e),
}

And that’s the basic usage! There are lots more bells-and-whistles in the form of exposed algorithm parameters, streaming APIs and other goodies that you can find by poking around this documentation.

§Memory Footprint

The following table lists the size of the on-disk bytes encoding and the in-memory struct size of the standard key objects:

Key ObjectPK size on diskPK size in memorySK Size on diskSK size in memory
ML-DSA-4413121312 (4128)256012464
ML-DSA-6519521952 (6176)403217584
ML-DSA-8725922592 (8224)489623728

The following table lists the size of the on-disk bytes encoding and the in-memory struct size of the expanded key objects that pre-expand the public matrix A for faster repeated verify() operations:

Key ObjectPK size on diskPK size in memorySK Size on diskSK size in memory
ML-DSA-44_expanded131220512256028848
ML-DSA-65_expanded195236896403248304
ML-DSA-87_expanded259265568489681072

All values are in bytes. The “in memory” sizes are measured by rust’s std::mem::size_of. Values in parentheses are the usual sizes in our un-optimized implementation in the [bouncycastle_mldsa] crate.

§Security

All functionality exposed by this crate is considered secure to use. In other words, this crate does not contain any “hazmat” except for the obvious points about handling your private keys properly: if you post your private key to github, or you generate production keys from a weak seed, I can’t help you, that’s on you. It is worth mentioning, however, that if using a MLDSA::keygen_from_seed, then it is your responsibility to ensure that the seed is cryptographically random and unpredictable.

While the full formulation of the ML-DSA and HashML-DSA algorithms look complex with parameters like seed, mu, ph, ctx, and rnd, rest assured that use (or misuse) of these parameters do not really affect security of the algorithm; they just mean that you might produce a signature that nobody else can verify.

A note about cryptographic side-channel attacks: considerable effort has been expended to attempt to make this implementation constant-time, which generally means that the core mathematical algorithm code that handles secret data uses bitshift-and-xor type constructions instead of if-and-loop constructions. That should give this implementation reasonably good resistance to timing and power analysis key extraction attacks, however: A) this is a “best-effort” and not formally verified, and B) the Rust compiler does not guarantee constant-time behaviour no matter how clever your code, so like all Safe Rust code (ie Rust code that does not include inline assembly), we are at the mercy of the Rust compiler’s optimizer for whether our bitshift-and-xor code actually remains constant-time after compilation.

Re-exports§

pub use hash_mldsa::HashMLDSA44_with_SHA256;
pub use hash_mldsa::HashMLDSA65_with_SHA256;
pub use hash_mldsa::HashMLDSA87_with_SHA256;
pub use hash_mldsa::HashMLDSA44_with_SHA512;
pub use hash_mldsa::HashMLDSA65_with_SHA512;
pub use hash_mldsa::HashMLDSA87_with_SHA512;
pub use mldsa::MuBuilder;
pub use mldsa::MLDSA;
pub use mldsa::MLDSA44;
pub use mldsa::MLDSA65;
pub use mldsa::MLDSA87;
pub use mldsa::MLDSATrait;
pub use mldsa::ML_DSA_44_NAME;
pub use mldsa::ML_DSA_65_NAME;
pub use mldsa::ML_DSA_87_NAME;
pub use hash_mldsa::HASH_ML_DSA_44_with_SHA256_NAME;
pub use hash_mldsa::HASH_ML_DSA_65_WITH_SHA256_NAME;
pub use hash_mldsa::HASH_ML_DSA_87_with_SHA256_NAME;
pub use hash_mldsa::HASH_ML_DSA_44_with_SHA512_NAME;
pub use hash_mldsa::HASH_ML_DSA_65_WITH_SHA512_NAME;
pub use hash_mldsa::HASH_ML_DSA_87_WITH_SHA512_NAME;
pub use mldsa::MLDSA_MU_LEN;
pub use mldsa::MLDSA_RND_LEN;
pub use mldsa::MLDSA_SEED_LEN;
pub use mldsa::MLDSA_TR_LEN;
pub use mldsa::MLDSA44_PK_LEN;
pub use mldsa::MLDSA44_SIG_LEN;
pub use mldsa::MLDSA44_SK_LEN;
pub use mldsa::MLDSA65_PK_LEN;
pub use mldsa::MLDSA65_SIG_LEN;
pub use mldsa::MLDSA65_SK_LEN;
pub use mldsa::MLDSA87_PK_LEN;
pub use mldsa::MLDSA87_SIG_LEN;
pub use mldsa::MLDSA87_SK_LEN;

Modules§

hash_mldsa
This implements the HashML-DSA algorithm specified in FIPS 204 which is useful for cases where you need to process the to-be-signed message in chunks, and you cannot use the external mu mode of MLDSA; possibly because you have to digest the message before you know which public key will sign it.
mldsa
This page documents advanced features of the Module Lattice Digital Signature Algorithm (ML-DSA) available in this crate.

Structs§

MLDSAPrivateKey
An ML-DSA private key.
MLDSAPrivateKeyExpanded
A fully expanded ML-DSA private key that includes the intermediate values needed for performing multiple sign operations with the same private key, which causes the private ey struct to take up more memory, but results in more efficient repeated sign() operations.
MLDSAPublicKey
An ML-DSA public key.
MLDSAPublicKeyExpanded
A fully expanded ML-DSA public key that includes the intermediate values needed for performing multiple verification operations against the same public key, which causes the public key struct to take up more memory, but results in more efficient repeated verify() operations.
Matrix
A matrix over the ML-DSA ring.
Polynomial
A polynomial over the ML-DSA ring. Dev note: this doesn’t strictly need to be pub … ie there’s no good reason for a caller to use this class directly, but in order to test the Debug and Display traits, you need STD, so those can’t be tested from inline tests in this file and the real unit tests are in a different crate, so here we are.

Traits§

MLDSAPrivateKeyTrait
General trait for all ML-DSA private keys types.
MLDSAPublicKeyTrait
General trait for all ML-DSA public keys types.

Type Aliases§

MLDSA44PrivateKey
ML-DSA-44 Private Key
MLDSA44PrivateKeyExpanded
ML-DSA-44 Private Key with a pre-expanded public matrix A for repeated decaps operations.
MLDSA44PublicKey
ML-DSA-44 Public Key
MLDSA44PublicKeyExpanded
ML-DSA-44 Public Key with a pre-expanded public matrix A for repeated encaps operations.
MLDSA65PrivateKey
ML-DSA-65 Private Key
MLDSA65PrivateKeyExpanded
ML-DSA-65 Private Key with a pre-expanded public matrix A for repeated decaps operations.
MLDSA65PublicKey
ML-DSA-65 Public Key
MLDSA65PublicKeyExpanded
ML-DSA-65 Public Key with a pre-expanded public matrix A for repeated encaps operations.
MLDSA87PrivateKey
ML-DSA-87 Private Key
MLDSA87PrivateKeyExpanded
ML-DSA-87 Private Key with a pre-expanded public matrix A for repeated decaps operations.
MLDSA87PublicKey
ML-DSA-87 Public Key
MLDSA87PublicKeyExpanded
ML-DSA-87 Public Key with a pre-expanded public matrix A for repeated encaps operations.