Skip to main content

MLDSA

Struct MLDSA 

Source
pub struct MLDSA<const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, PK: MLDSAPublicKeyTrait<k, PK_LEN> + MLDSAPublicKeyInternalTrait<k, PK_LEN>, SK: MLDSAPrivateKeyTrait<k, l, ETA, SK_LEN, PK_LEN> + MLDSAPrivateKeyInternalTrait<k, l, ETA, SK_LEN, PK_LEN>, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, const GAMMA2: i32, const k: usize, const l: usize, const ETA: usize, const BETA: i32, const OMEGA: i32, const C_TILDE: usize, const POLY_VEC_H_PACKED_LEN: usize, const POLY_W1_PACKED_LEN: usize, const W1_PACKED_LEN: usize, const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize> { /* private fields */ }
Expand description

The core internal implementation of the ML-DSA algorithm. This needs to be public for the compiler to be able to find it, but you shouldn’t ever need to use this directly. Please use the named public types.

Implementations§

Source§

impl<const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, PK: MLDSAPublicKeyTrait<k, PK_LEN> + MLDSAPublicKeyInternalTrait<k, PK_LEN>, SK: MLDSAPrivateKeyTrait<k, l, ETA, SK_LEN, PK_LEN> + MLDSAPrivateKeyInternalTrait<k, l, ETA, SK_LEN, PK_LEN>, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, const GAMMA2: i32, const k: usize, const l: usize, const ETA: usize, const BETA: i32, const OMEGA: i32, const C_TILDE: usize, const POLY_Z_PACKED_LEN: usize, const POLY_W1_PACKED_LEN: usize, const W1_PACKED_LEN: usize, const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize> MLDSA<PK_LEN, SK_LEN, SIG_LEN, PK, SK, TAU, LAMBDA, GAMMA1, GAMMA2, k, l, ETA, BETA, OMEGA, C_TILDE, POLY_Z_PACKED_LEN, POLY_W1_PACKED_LEN, W1_PACKED_LEN, POLY_ETA_PACKED_LEN, LAMBDA_over_4, GAMMA1_MASK_LEN>

Source

pub fn keygen_from_os_rng() -> Result<(PK, SK), SignatureError>

Should still be ok in FIPS mode

Trait Implementations§

Source§

impl<const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, PK: MLDSAPublicKeyTrait<k, PK_LEN> + MLDSAPublicKeyInternalTrait<k, PK_LEN>, SK: MLDSAPrivateKeyTrait<k, l, ETA, SK_LEN, PK_LEN> + MLDSAPrivateKeyInternalTrait<k, l, ETA, SK_LEN, PK_LEN>, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, const GAMMA2: i32, const k: usize, const l: usize, const ETA: usize, const BETA: i32, const OMEGA: i32, const C_TILDE: usize, const POLY_Z_PACKED_LEN: usize, const POLY_W1_PACKED_LEN: usize, const W1_PACKED_LEN: usize, const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize> MLDSATrait<PK_LEN, SK_LEN, SIG_LEN, PK, SK, k, l, ETA> for MLDSA<PK_LEN, SK_LEN, SIG_LEN, PK, SK, TAU, LAMBDA, GAMMA1, GAMMA2, k, l, ETA, BETA, OMEGA, C_TILDE, POLY_Z_PACKED_LEN, POLY_W1_PACKED_LEN, W1_PACKED_LEN, POLY_ETA_PACKED_LEN, LAMBDA_over_4, GAMMA1_MASK_LEN>

Source§

fn keygen_from_seed( seed: &KeyMaterialSized<32>, ) -> Result<(PK, SK), SignatureError>

Imports a secret key from a seed.

Source§

fn keygen_from_seed_and_encoded( seed: &KeyMaterialSized<32>, encoded_sk: &[u8; SK_LEN], ) -> Result<(PK, SK), SignatureError>

Imports a secret key from both a seed and an encoded_sk.

This is a convenience function to expand the key from seed and compare it against the provided encoded_sk using a constant-time equality check. If everything checks out, the secret key is returned fully populated with pk and seed. If the provided key and derived key don’t match, an error is returned.

Source§

fn keypair_consistency_check(pk: &PK, sk: &SK) -> Result<(), SignatureError>

Given a public key and a secret key, check that the public key matches the secret key. This is a sanity check that the public key was generated correctly from the secret key.

At the current time, this is only possible if sk either contains a public key (in which case the two pk’s are encoded and compared for byte equality), or if sk contains a seed (in which case a keygen_from_seed is run and then the pk’s compared).

Returns either () or SignatureError::ConsistencyCheckFailed.

Source§

fn compute_mu_from_tr( msg: &[u8], ctx: Option<&[u8]>, tr: &[u8; 64], ) -> Result<[u8; 64], SignatureError>

This provides the first half of the “External Mu” interface to ML-DSA which is described in, and allowed under, NIST’s FAQ that accompanies FIPS 204.

This function, together with MLDSATrait::sign_mu perform a complete ML-DSA signature which is indistinguishable from one produced by the one-shot sign APIs.

The utility of this function is exactly as described on Line 6 of Algorithm 7 of FIPS 204:

message representative that may optionally be computed in a different cryptographic module

The utility is when an extremely large message needs to be signed, where the message exists on one computing system and the private key to sign it is held on another and either the transfer time or bandwidth causes operational concerns (this is common for example with network HSMs or sending large messages to be signed by a smartcard communicating over near-field radio). Another use case is if the contents of the message are sensitive and the signer does not want to transmit the message itself for fear of leaking it via proxy logging and instead would prefer to only transmit a hash of it.

Since “External Mu” mode is well-defined by FIPS 204 and allowed by NIST, the mu value produced here can be used with many hardware crypto modules.

This “External Mu” mode of ML-DSA provides an alternative to the HashML-DSA algorithm in that it allows the message to be externally pre-hashed, however, unlike HashML-DSA, this is merely an optimization between the application holding the to-be-signed message and the cryptographic module holding the private key – in particular, while HashML-DSA requires the verifier to know whether ML-DSA or HashML-DSA was used to sign the message, both “direct” ML-DSA and “External Mu” signatures can be verified with a standard ML-DSA verifier.

This function requires the public key hash tr, which can be computed from the public key using MLDSAPublicKeyTrait::compute_tr.

For a streaming version of this, see MuBuilder.

Source§

fn compute_mu_from_pk( msg: &[u8], ctx: Option<&[u8]>, pk: &PK, ) -> Result<[u8; 64], SignatureError>

Same as MLDSA::compute_mu_from_tr, but extracts tr from the public key.

Source§

fn compute_mu_from_sk( msg: &[u8], ctx: Option<&[u8]>, sk: &SK, ) -> Result<[u8; 64], SignatureError>

Same as MLDSA::compute_mu_from_tr, but extracts tr from the private key.

Source§

fn sign_mu(sk: &SK, mu: &[u8; 64]) -> Result<[u8; SIG_LEN], SignatureError>

Performs an ML-DSA signature using the provided external message representative mu. This implements FIPS 204 Algorithm 7 with line 6 removed; a modification that is allowed by both FIPS 204 itself, as well as subsequent FAQ documents. This mode uses randomized signing (called “hedged mode” in FIPS 204) using an internal RNG.

Source§

fn sign_mu_out( sk: &SK, mu: &[u8; 64], output: &mut [u8; SIG_LEN], ) -> Result<usize, SignatureError>

Performs an ML-DSA signature using the provided external message representative mu. This implements FIPS 204 Algorithm 7 with line 6 removed; a modification that is allowed by both FIPS 204 itself, as well as subsequent FAQ documents. This mode uses randomized signing (called “hedged mode” in FIPS 204) using an internal RNG.

Returns the number of bytes written to the output buffer. Can be called with an oversized buffer.

Source§

fn sign_mu_deterministic( sk: &SK, mu: &[u8; 64], rnd: [u8; 32], ) -> Result<[u8; SIG_LEN], SignatureError>

Algorithm 7 ML-DSA.Sign_internal(𝑠𝑘, 𝑀′, 𝑟𝑛𝑑) (modified to take an externally-computed mu instead of M’)

Performs an ML-DSA signature using the provided external message representative mu. This implements FIPS 204 Algorithm 7 with line 6 removed; a modification that is allowed by both FIPS 204 itself, as well as subsequent FAQ documents.

Security note: This mode exposes deterministic signing (called “hedged mode” and allowed by FIPS 204). The ML-DSA algorithm is considered safe to use in deterministic mode, but be aware that the responsibility is on you to ensure that your nonce rnd is unique per signature. If not, you may lose some privacy properties; for example it becomes easy to tell if a signer has signed the same message twice or two different messagase, or to tell if the same message has been signed by the same signer twice or two different signers.

Since rnd should be either a per-signature nonce, or a fixed value, therefore, to help prevent accidental nonce reuse, this function moves rnd.

Source§

fn sign_mu_deterministic_out( sk: &SK, mu: &[u8; 64], rnd: [u8; 32], output: &mut [u8; SIG_LEN], ) -> Result<usize, SignatureError>

Algorithm 7 ML-DSA.Sign_internal(𝑠𝑘, 𝑀′, 𝑟𝑛𝑑) (modified to take an externally-computed mu instead of M’)

Performs an ML-DSA signature using the provided external message representative mu. This implements FIPS 204 Algorithm 7 with line 6 removed; a modification that is allowed by both FIPS 204 itself, as well as subsequent FAQ documents. This mode exposes deterministic signing (called “hedged mode” in FIPS 204) using an internal RNG.

Since rnd should be either a per-signature nonce, or a fixed value, therefore, to help prevent accidental nonce reuse, this function moves rnd.

Returns the number of bytes written to the output buffer. Can be called with an oversized buffer.

Source§

fn set_signer_rnd(&mut self, rnd: [u8; 32])

To be used for deterministic signing in conjunction with the MLDSA44::sign_init, MLDSA44::sign_update, and MLDSA44::sign_final flow. Can be set anywhere after MLDSA44::sign_init and before MLDSA44::sign_final

Source§

fn sign_init_from_seed( seed: &KeyMaterialSized<32>, ctx: Option<&[u8]>, ) -> Result<Self, SignatureError>

Alternative initialization of the streaming signer where you have your private key as a seed and you want to delay its expansion as late as possible for memory-usage reasons.

Source§

fn verify_mu_internal(pk: &PK, mu: &[u8; 64], sig: &[u8; SIG_LEN]) -> bool

Algorithm 8 ML-DSA.Verify_internal(𝑝𝑘, 𝑀′, 𝜎) Internal function to verify a signature 𝜎 for a formatted message 𝑀′ . Input: Public key 𝑝𝑘 ∈ 𝔹32+32𝑘(bitlen (𝑞−1)−𝑑) and message 𝑀′ ∈ {0, 1}∗ . Input: Signature 𝜎 ∈ 𝔹𝜆/4+ℓ⋅32⋅(1+bitlen (𝛾1−1))+𝜔+𝑘.

Source§

fn sign_mu_deterministic_from_seed( seed: &KeyMaterialSized<32>, mu: &[u8; 64], rnd: [u8; 32], ) -> Result<[u8; SIG_LEN], SignatureError>

This contains a heavily-optimized combined keygen() and sign() which aims to reduce peak memory usage by never having the full secret key in memory at the same time, and by deriving intermediate values piece-wise as needed.
Source§

fn sign_mu_deterministic_from_seed_out( seed: &KeyMaterialSized<32>, mu: &[u8; 64], rnd: [u8; 32], output: &mut [u8; SIG_LEN], ) -> Result<usize, SignatureError>

This contains a heavily-optimized combined keygen() and sign() which aims to reduce peak memory usage by never having the full secret key in memory at the same time, and by deriving intermediate values piece-wise as needed.
Source§

impl<const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, PK: MLDSAPublicKeyTrait<k, PK_LEN> + MLDSAPublicKeyInternalTrait<k, PK_LEN>, SK: MLDSAPrivateKeyTrait<k, l, ETA, SK_LEN, PK_LEN> + MLDSAPrivateKeyInternalTrait<k, l, ETA, SK_LEN, PK_LEN>, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, const GAMMA2: i32, const k: usize, const l: usize, const ETA: usize, const BETA: i32, const OMEGA: i32, const C_TILDE: usize, const POLY_Z_PACKED_LEN: usize, const POLY_W1_PACKED_LEN: usize, const W1_PACKED_LEN: usize, const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize> Signature<PK, SK> for MLDSA<PK_LEN, SK_LEN, SIG_LEN, PK, SK, TAU, LAMBDA, GAMMA1, GAMMA2, k, l, ETA, BETA, OMEGA, C_TILDE, POLY_Z_PACKED_LEN, POLY_W1_PACKED_LEN, W1_PACKED_LEN, POLY_ETA_PACKED_LEN, LAMBDA_over_4, GAMMA1_MASK_LEN>

Source§

fn keygen() -> Result<(PK, SK), SignatureError>

Generate a keypair. Error condition: Basically only on RNG failures
Source§

fn sign( sk: &SK, msg: &[u8], ctx: Option<&[u8]>, ) -> Result<Vec<u8>, SignatureError>

Produce a signature for the provided message and context. Both the msg and ctx accept zero-length byte arrays. Read more
Source§

fn sign_out( sk: &SK, msg: &[u8], ctx: Option<&[u8]>, output: &mut [u8], ) -> Result<usize, SignatureError>

Returns the number of bytes written to the output buffer. Can be called with an oversized buffer.
Source§

fn sign_init(sk: &SK, ctx: Option<&[u8]>) -> Result<Self, SignatureError>

Initialize a signer for streaming mode with the provided private key.
Source§

fn sign_update(&mut self, msg_chunk: &[u8])

Source§

fn sign_final(self) -> Result<Vec<u8>, SignatureError>

Complete the signing operation. Consumes self.
Source§

fn sign_final_out(self, output: &mut [u8]) -> Result<usize, SignatureError>

Returns the number of bytes written to the output buffer. Can be called with an oversized buffer.
Source§

fn verify( pk: &PK, msg: &[u8], ctx: Option<&[u8]>, sig: &[u8], ) -> Result<(), SignatureError>

On success, returns Ok(()) On failure, returns Err(SignatureError::SignatureVerificationFailed); may also return other types of SignatureError as appropriate (such as for invalid-length inputs).
Source§

fn verify_init(pk: &PK, ctx: Option<&[u8]>) -> Result<Self, SignatureError>

Source§

fn verify_update(&mut self, msg_chunk: &[u8])

Source§

fn verify_final(self, sig: &[u8]) -> Result<(), SignatureError>

On success, returns Ok(()) On failure, returns Err(SignatureError::SignatureVerificationFailed); may also return other types of SignatureError as appropriate (such as for invalid-length inputs).

Auto Trait Implementations§

§

impl<const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, PK, SK, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, const GAMMA2: i32, const k: usize, const l: usize, const ETA: usize, const BETA: i32, const OMEGA: i32, const C_TILDE: usize, const POLY_VEC_H_PACKED_LEN: usize, const POLY_W1_PACKED_LEN: usize, const W1_PACKED_LEN: usize, const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize> Freeze for MLDSA<PK_LEN, SK_LEN, SIG_LEN, PK, SK, TAU, LAMBDA, GAMMA1, GAMMA2, k, l, ETA, BETA, OMEGA, C_TILDE, POLY_VEC_H_PACKED_LEN, POLY_W1_PACKED_LEN, W1_PACKED_LEN, POLY_ETA_PACKED_LEN, LAMBDA_over_4, GAMMA1_MASK_LEN>
where SK: Freeze, PK: Freeze,

§

impl<const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, PK, SK, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, const GAMMA2: i32, const k: usize, const l: usize, const ETA: usize, const BETA: i32, const OMEGA: i32, const C_TILDE: usize, const POLY_VEC_H_PACKED_LEN: usize, const POLY_W1_PACKED_LEN: usize, const W1_PACKED_LEN: usize, const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize> RefUnwindSafe for MLDSA<PK_LEN, SK_LEN, SIG_LEN, PK, SK, TAU, LAMBDA, GAMMA1, GAMMA2, k, l, ETA, BETA, OMEGA, C_TILDE, POLY_VEC_H_PACKED_LEN, POLY_W1_PACKED_LEN, W1_PACKED_LEN, POLY_ETA_PACKED_LEN, LAMBDA_over_4, GAMMA1_MASK_LEN>

§

impl<const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, PK, SK, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, const GAMMA2: i32, const k: usize, const l: usize, const ETA: usize, const BETA: i32, const OMEGA: i32, const C_TILDE: usize, const POLY_VEC_H_PACKED_LEN: usize, const POLY_W1_PACKED_LEN: usize, const W1_PACKED_LEN: usize, const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize> Send for MLDSA<PK_LEN, SK_LEN, SIG_LEN, PK, SK, TAU, LAMBDA, GAMMA1, GAMMA2, k, l, ETA, BETA, OMEGA, C_TILDE, POLY_VEC_H_PACKED_LEN, POLY_W1_PACKED_LEN, W1_PACKED_LEN, POLY_ETA_PACKED_LEN, LAMBDA_over_4, GAMMA1_MASK_LEN>
where SK: Send, PK: Send,

§

impl<const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, PK, SK, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, const GAMMA2: i32, const k: usize, const l: usize, const ETA: usize, const BETA: i32, const OMEGA: i32, const C_TILDE: usize, const POLY_VEC_H_PACKED_LEN: usize, const POLY_W1_PACKED_LEN: usize, const W1_PACKED_LEN: usize, const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize> Sync for MLDSA<PK_LEN, SK_LEN, SIG_LEN, PK, SK, TAU, LAMBDA, GAMMA1, GAMMA2, k, l, ETA, BETA, OMEGA, C_TILDE, POLY_VEC_H_PACKED_LEN, POLY_W1_PACKED_LEN, W1_PACKED_LEN, POLY_ETA_PACKED_LEN, LAMBDA_over_4, GAMMA1_MASK_LEN>
where SK: Sync, PK: Sync,

§

impl<const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, PK, SK, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, const GAMMA2: i32, const k: usize, const l: usize, const ETA: usize, const BETA: i32, const OMEGA: i32, const C_TILDE: usize, const POLY_VEC_H_PACKED_LEN: usize, const POLY_W1_PACKED_LEN: usize, const W1_PACKED_LEN: usize, const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize> Unpin for MLDSA<PK_LEN, SK_LEN, SIG_LEN, PK, SK, TAU, LAMBDA, GAMMA1, GAMMA2, k, l, ETA, BETA, OMEGA, C_TILDE, POLY_VEC_H_PACKED_LEN, POLY_W1_PACKED_LEN, W1_PACKED_LEN, POLY_ETA_PACKED_LEN, LAMBDA_over_4, GAMMA1_MASK_LEN>
where SK: Unpin, PK: Unpin,

§

impl<const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, PK, SK, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, const GAMMA2: i32, const k: usize, const l: usize, const ETA: usize, const BETA: i32, const OMEGA: i32, const C_TILDE: usize, const POLY_VEC_H_PACKED_LEN: usize, const POLY_W1_PACKED_LEN: usize, const W1_PACKED_LEN: usize, const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize> UnsafeUnpin for MLDSA<PK_LEN, SK_LEN, SIG_LEN, PK, SK, TAU, LAMBDA, GAMMA1, GAMMA2, k, l, ETA, BETA, OMEGA, C_TILDE, POLY_VEC_H_PACKED_LEN, POLY_W1_PACKED_LEN, W1_PACKED_LEN, POLY_ETA_PACKED_LEN, LAMBDA_over_4, GAMMA1_MASK_LEN>
where SK: UnsafeUnpin, PK: UnsafeUnpin,

§

impl<const PK_LEN: usize, const SK_LEN: usize, const SIG_LEN: usize, PK, SK, const TAU: i32, const LAMBDA: i32, const GAMMA1: i32, const GAMMA2: i32, const k: usize, const l: usize, const ETA: usize, const BETA: i32, const OMEGA: i32, const C_TILDE: usize, const POLY_VEC_H_PACKED_LEN: usize, const POLY_W1_PACKED_LEN: usize, const W1_PACKED_LEN: usize, const POLY_ETA_PACKED_LEN: usize, const LAMBDA_over_4: usize, const GAMMA1_MASK_LEN: usize> UnwindSafe for MLDSA<PK_LEN, SK_LEN, SIG_LEN, PK, SK, TAU, LAMBDA, GAMMA1, GAMMA2, k, l, ETA, BETA, OMEGA, C_TILDE, POLY_VEC_H_PACKED_LEN, POLY_W1_PACKED_LEN, W1_PACKED_LEN, POLY_ETA_PACKED_LEN, LAMBDA_over_4, GAMMA1_MASK_LEN>
where SK: UnwindSafe, PK: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.