pub fn sign_internal<P: Params>(
sk: &[u8],
m_prime: &[u8],
rnd: &[u8; 32],
) -> Result<Vec<u8>, MlDsaError>Expand description
Sign a pre-formatted message (deterministic or hedged).
Implements Algorithm 7 of FIPS 204 (ML-DSA.Sign_internal).
This function contains the core rejection sampling loop: candidate
signatures (z, h) are generated from a masking vector y and the
challenge polynomial c, then tested against the norm bounds
||z||_inf < gamma1 - beta and ||r0||_inf < gamma2 - beta. If any
check fails, the counter kappa is incremented and a new attempt begins.
sk: encoded secret key bytes.m_prime: pre-formatted message (e.g.,0x00 || len(ctx) || ctx || msg).rnd: 32-byte randomness. Use random bytes for hedged signing or all-zeros for fully deterministic signing.
§Side-channel countermeasures
With the sca-protected Cargo feature enabled (default), this
function activates the additional defences described in the
crate-level documentation:
- Shuffled NTT on
s1,s2,t0— runs once at entry, viasuper::shuffle::ntt_shuffled. Defends against SPA on the secret-key NTT and disrupts trace alignment for any later DPA campaign that tries to average aligned traces. - First-order additive masking of the NTT-domain secrets,
via
super::masked::MaskedPoly. Each polynomial is split into two shares modq = 8 380 417; no single intermediate value reveals the secret to a first-order observer. - Per-iteration
c·sₓmultiplications go throughsuper::masked::masked_pointwise_mul_public, which multiplies each share independently by the public challengeĉ. Becauseĉis public, first-order shares are sufficient — no secret×secret operation is performed. - Mask refresh after every use: the share pair is
re-randomized via
MaskedPoly::refresh()between rejection iterations, so the same secret never multiplies the same share twice — defeating higher-order correlation attacks that would otherwise become available across many rejection retries on the same key.
All randomness for the SCA layer comes from a deterministic
SHAKE256-based ScaRng seeded with (K ‖ rnd ‖ tr ‖ M'), so
the function remains deterministic for fixed rnd. The masked
path produces signatures bit-identical to the unmasked path
— proven by the NIST ACVP siggen vectors, which the SCA build
passes unchanged.
§Errors
Returns MlDsaError::InvalidSecretKey if sk has incorrect length
(checked by the caller in the public API).