44import java .security .SecureRandom ;
55
66import org .bouncycastle .asn1 .ASN1Encoding ;
7+ import org .bouncycastle .asn1 .ASN1ObjectIdentifier ;
78import org .bouncycastle .crypto .CipherParameters ;
89import org .bouncycastle .crypto .CryptoException ;
910import org .bouncycastle .crypto .DataLengthException ;
1011import org .bouncycastle .crypto .Digest ;
1112import org .bouncycastle .crypto .Signer ;
13+ import org .bouncycastle .crypto .digests .SHA512Digest ;
14+ import org .bouncycastle .crypto .digests .SHAKEDigest ;
1215import org .bouncycastle .crypto .params .ParametersWithContext ;
1316import org .bouncycastle .crypto .params .ParametersWithRandom ;
1417import org .bouncycastle .pqc .crypto .DigestUtils ;
@@ -78,17 +81,23 @@ public void init(boolean forSigning, CipherParameters param)
7881
7982 engine .initVerify (pubKey .rho , pubKey .t1 , true , ctx );
8083 }
81- digest = engine .shake256Digest ;
82- byte [] digestOIDEncoding ;
84+
85+ initDigest (parameters );
86+ }
87+
88+ private void initDigest (MLDSAParameters parameters )
89+ {
90+ digest = createDigest (parameters );
91+
92+ ASN1ObjectIdentifier oid = DigestUtils .getDigestOid (digest .getAlgorithmName ());
8393 try
8494 {
85- digestOIDEncoding = DigestUtils . getDigestOid ( digest . getAlgorithmName ()) .getEncoded (ASN1Encoding .DER );
95+ digestOIDEncoding = oid .getEncoded (ASN1Encoding .DER );
8696 }
8797 catch (IOException e )
8898 {
8999 throw new IllegalStateException ("oid encoding failed: " + e .getMessage ());
90100 }
91- digest .update (digestOIDEncoding , 0 , digestOIDEncoding .length );
92101 }
93102
94103 public void update (byte b )
@@ -101,22 +110,25 @@ public void update(byte[] in, int off, int len)
101110 digest .update (in , off , len );
102111 }
103112
104- public byte [] generateSignature ()
105- throws CryptoException , DataLengthException
113+ public byte [] generateSignature () throws CryptoException , DataLengthException
106114 {
115+ SHAKEDigest msgDigest = finishPreHash ();
116+
107117 byte [] rnd = new byte [MLDSAEngine .RndBytes ];
108118 if (random != null )
109119 {
110120 random .nextBytes (rnd );
111121 }
112- byte [] mu = engine .generateMu (engine .shake256Digest );
113- return engine .generateSignature (mu , engine .getShake256Digest (), privKey .rho , privKey .k , privKey .t0 , privKey .s1 , privKey .s2 , rnd );
122+ byte [] mu = engine .generateMu (msgDigest );
123+
124+ return engine .generateSignature (mu , msgDigest , privKey .rho , privKey .k , privKey .t0 , privKey .s1 , privKey .s2 , rnd );
114125 }
115126
116127 public boolean verifySignature (byte [] signature )
117128 {
118- byte [] mu = engine .generateMu (engine .shake256Digest );
119- return engine .verifyInternalMuSignature (mu , signature , signature .length , engine .getShake256Digest (), pubKey .rho , pubKey .t1 );
129+ SHAKEDigest msgDigest = finishPreHash ();
130+
131+ return engine .verifyInternal (signature , signature .length , msgDigest , pubKey .rho , pubKey .t1 );
120132 }
121133
122134 /**
@@ -127,8 +139,20 @@ public void reset()
127139 digest .reset ();
128140 }
129141
142+ private SHAKEDigest finishPreHash ()
143+ {
144+ byte [] hash = new byte [digest .getDigestSize ()];
145+ digest .doFinal (hash , 0 );
146+
147+ SHAKEDigest msgDigest = engine .getShake256Digest ();
148+ // TODO It should be possible to include digestOIDEncoding in the memo'ed digest
149+ msgDigest .update (digestOIDEncoding , 0 , digestOIDEncoding .length );
150+ msgDigest .update (hash , 0 , hash .length );
151+ return msgDigest ;
152+ }
153+
130154// TODO: these are probably no longer correct and also need to be marked as protected
131- // protected byte[] internalGenerateSignature(byte[] message, SecureRandom random)
155+ // protected byte[] internalGenerateSignature(byte[] message, byte[] random)
132156// {
133157// MLDSAEngine engine = privKey.getParameters().getEngine(random);
134158//
@@ -142,19 +166,15 @@ public void reset()
142166// return engine.verifyInternal(signature, signature.length, message, message.length, pubKey.rho, pubKey.t1);
143167// }
144168
145- // private static Digest createDigest(MLDSAParameters parameters)
146- // {
147- //TODO: MLDSA44 may use SHA2-256, SHA3-256, SHAKE128
148- // MLDSA65 may use SHA3-384, SHA2-512
149- // MLDSA44/65/87 may use SHA2-512, SHA3-512, SHAKE256
150-
151- // switch (parameters.getType())
152- // {
153- // case MLDSAParameters.TYPE_PURE:
154- // case MLDSAParameters.TYPE_SHA2_512:
155- // return new SHAKEDigest(256);
156- // default:
157- // throw new IllegalArgumentException("unknown parameters type");
158- // }
159- // }
169+ private static Digest createDigest (MLDSAParameters parameters )
170+ {
171+ switch (parameters .getType ())
172+ {
173+ case MLDSAParameters .TYPE_PURE :
174+ case MLDSAParameters .TYPE_SHA2_512 :
175+ return new SHA512Digest ();
176+ default :
177+ throw new IllegalArgumentException ("unknown parameters type" );
178+ }
179+ }
160180}
0 commit comments