Class MLDSAEngine
- java.lang.Object
-
- org.bouncycastle.crypto.signers.mldsa.MLDSAEngine
-
public class MLDSAEngine extends java.lang.ObjectLightweight ML-DSA (FIPS 204) engine — key generation, signing and verification.Constant-time note. ML-DSA is designed to admit a constant-time implementation, and this engine keeps the secret-sensitive arithmetic branchless and free of secret-indexed memory access: the NTT (
Ntt), the Montgomery/Barrett reductions andconditionalAddQ(Reduce),Rounding.decompose(int, int)andpower2RoundAllall operate over public loop bounds with mask-select rather than data-dependent branches, and ML-DSA uses no secret-indexed table lookups.The following operations are deliberately variable-time. Each matches the FIPS 204 / pq-crystals reference and its accepted side-channel model — do not "simplify" them into a shape that leaks more:
- Rejection sampling of
s1/s2(Poly.uniformEta(byte[], short)): the number of SHAKE bytes consumed depends on the secret seed, but only the reject count between accepted coefficients leaks — never an accepted coefficient value. Matches referencerej_eta. - The Fiat-Shamir-with-aborts loop (
generateSignature(byte[], org.bouncycastle.crypto.digests.SHAKEDigest, byte[], byte[], byte[], byte[], byte[], byte[])): the iteration count and whichcheckNorm/makeHintbound triggered the restart leak through timing. A rejected attempt discardsyand resamples, so this reveals nothing about the long-term key. Poly.checkNorm(int)early-returns on the first out-of-bound coefficient. The absolute value is computed branchlessly first so a secret coefficient's sign never leaks — only the rejection event does, exactly as the referencepoly_chknormintends.Rounding.makeHint(int, int, org.bouncycastle.crypto.signers.mldsa.MLDSAEngine)branches on its inputs, but the result is the hint bit that ships in the signature — information-equivalent to public output.Poly.challenge(byte[], int, int)(SampleInBall) has a data-dependent rejection loop andc[b]access, butbderives from the public commitment hash c~ (part of the signature / recomputed by the verifier), so no secret is involved.
decompose) preserves all of the above: it adds no secret-dependent branch, memory index, or variable-latency operation. - Rejection sampling of
-
-
Field Summary
Fields Modifier and Type Field Description static intCrhBytesstatic intDilithiumDstatic intDilithiumNstatic intDilithiumPolyT0PackedBytesstatic intDilithiumPolyT1PackedBytesstatic intDilithiumQstatic intDilithiumQinvstatic intRndBytesstatic intSeedBytesstatic intTrBytes
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description byte[]deriveT1(byte[] rho, byte[] key, byte[] tr, byte[] s1Enc, byte[] s2Enc, byte[] t0Enc)byte[][]generateKeyPair()byte[][]generateKeyPairInternal(byte[] seed)byte[]generateMu(SHAKEDigest shake256Digest)byte[]generateSignature(byte[] mu, SHAKEDigest shake256Digest, byte[] rho, byte[] key, byte[] t0Enc, byte[] s1Enc, byte[] s2Enc, byte[] rnd)intgetDilithiumK()intgetDilithiumL()intgetDilithiumPolyEtaPackedBytes()static MLDSAEnginegetInstance(MLDSAParameters mldsaParameters, java.security.SecureRandom random)SHAKEDigestgetShake256Digest()protected org.bouncycastle.crypto.signers.mldsa.SymmetricGetSymmetric()voidinitSign(byte[] tr, boolean isPreHash, byte[] ctx)voidinitVerify(byte[] rho, byte[] encT1, boolean isPreHash, byte[] ctx)byte[]signInternal(byte[] msg, int msglen, byte[] rho, byte[] key, byte[] t0Enc, byte[] s1Enc, byte[] s2Enc, byte[] rnd)booleanverifyInternal(byte[] sig, int siglen, SHAKEDigest shake256Digest, byte[] rho, byte[] encT1)booleanverifyInternalMu(byte[] providedMu)booleanverifyInternalMuSignature(byte[] mu, byte[] sig, int siglen, SHAKEDigest shake256Digest, byte[] rho, byte[] encT1)
-
-
-
Field Detail
-
DilithiumN
public static final int DilithiumN
- See Also:
- Constant Field Values
-
DilithiumQ
public static final int DilithiumQ
- See Also:
- Constant Field Values
-
DilithiumQinv
public static final int DilithiumQinv
- See Also:
- Constant Field Values
-
DilithiumD
public static final int DilithiumD
- See Also:
- Constant Field Values
-
SeedBytes
public static final int SeedBytes
- See Also:
- Constant Field Values
-
CrhBytes
public static final int CrhBytes
- See Also:
- Constant Field Values
-
RndBytes
public static final int RndBytes
- See Also:
- Constant Field Values
-
TrBytes
public static final int TrBytes
- See Also:
- Constant Field Values
-
DilithiumPolyT1PackedBytes
public static final int DilithiumPolyT1PackedBytes
- See Also:
- Constant Field Values
-
DilithiumPolyT0PackedBytes
public static final int DilithiumPolyT0PackedBytes
- See Also:
- Constant Field Values
-
-
Method Detail
-
GetSymmetric
protected org.bouncycastle.crypto.signers.mldsa.Symmetric GetSymmetric()
-
getDilithiumPolyEtaPackedBytes
public int getDilithiumPolyEtaPackedBytes()
-
getDilithiumK
public int getDilithiumK()
-
getDilithiumL
public int getDilithiumL()
-
getInstance
public static MLDSAEngine getInstance(MLDSAParameters mldsaParameters, java.security.SecureRandom random)
-
generateKeyPairInternal
public byte[][] generateKeyPairInternal(byte[] seed)
-
deriveT1
public byte[] deriveT1(byte[] rho, byte[] key, byte[] tr, byte[] s1Enc, byte[] s2Enc, byte[] t0Enc)
-
getShake256Digest
public SHAKEDigest getShake256Digest()
-
initSign
public void initSign(byte[] tr, boolean isPreHash, byte[] ctx)
-
initVerify
public void initVerify(byte[] rho, byte[] encT1, boolean isPreHash, byte[] ctx)
-
signInternal
public byte[] signInternal(byte[] msg, int msglen, byte[] rho, byte[] key, byte[] t0Enc, byte[] s1Enc, byte[] s2Enc, byte[] rnd)
-
generateMu
public byte[] generateMu(SHAKEDigest shake256Digest)
-
generateSignature
public byte[] generateSignature(byte[] mu, SHAKEDigest shake256Digest, byte[] rho, byte[] key, byte[] t0Enc, byte[] s1Enc, byte[] s2Enc, byte[] rnd)
-
verifyInternalMu
public boolean verifyInternalMu(byte[] providedMu)
-
verifyInternalMuSignature
public boolean verifyInternalMuSignature(byte[] mu, byte[] sig, int siglen, SHAKEDigest shake256Digest, byte[] rho, byte[] encT1)
-
verifyInternal
public boolean verifyInternal(byte[] sig, int siglen, SHAKEDigest shake256Digest, byte[] rho, byte[] encT1)
-
generateKeyPair
public byte[][] generateKeyPair()
-
-