Bouncy Castle Cryptography Library 1.85

org.bouncycastle.crypto.signers.mldsa
Class MLDSAEngine

java.lang.Object
  extended byorg.bouncycastle.crypto.signers.mldsa.MLDSAEngine

public class MLDSAEngine
extends java.lang.Object

Lightweight 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 and (Reduce), Rounding#decompose and all 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 / (Poly#uniformEta): 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 reference . The Fiat-Shamir-with-aborts loop (generateSignature(byte[], org.bouncycastle.crypto.digests.SHAKEDigest, byte[], byte[], byte[], byte[], byte[], byte[])): the iteration count and which / bound triggered the restart leak through timing. A rejected attempt discards and resamples, so this reveals nothing about the long-term key. Poly#checkNorm 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 reference intends. Rounding#makeHint branches on its inputs, but the result is the hint bit that ships in the signature — information-equivalent to public output. Poly#challenge (SampleInBall) has a data-dependent rejection loop and access, but derives from the public commitment hash c~ (part of the signature / recomputed by the verifier), so no secret is involved. The performance refactor of this package (in-place NTT, fused pointwise-accumulate, direct coefficient access, packed ) preserves all of the above: it adds no secret-dependent branch, memory index, or variable-latency operation.


Field Summary
static int CrhBytes
           
static int DilithiumD
           
static int DilithiumN
           
static int DilithiumPolyT0PackedBytes
           
static int DilithiumPolyT1PackedBytes
           
static int DilithiumQ
           
static int DilithiumQinv
           
static int RndBytes
           
static int SeedBytes
           
static int TrBytes
           
 
Method Summary
 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)
           
 int getDilithiumK()
           
 int getDilithiumL()
           
 int getDilithiumPolyEtaPackedBytes()
           
static MLDSAEngine getInstance(MLDSAParameters mldsaParameters, java.security.SecureRandom random)
           
 SHAKEDigest getShake256Digest()
           
protected  org.bouncycastle.crypto.signers.mldsa.Symmetric GetSymmetric()
           
 void initSign(byte[] tr, boolean isPreHash, byte[] ctx)
           
 void initVerify(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)
           
 boolean verifyInternal(byte[] sig, int siglen, SHAKEDigest shake256Digest, byte[] rho, byte[] encT1)
           
 boolean verifyInternalMu(byte[] providedMu)
           
 boolean verifyInternalMuSignature(byte[] mu, byte[] sig, int siglen, SHAKEDigest shake256Digest, byte[] rho, byte[] encT1)
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

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()

Bouncy Castle Cryptography Library 1.85