1515import org .bouncycastle .crypto .params .ParametersWithContext ;
1616import org .bouncycastle .crypto .params .ParametersWithRandom ;
1717import org .bouncycastle .pqc .crypto .DigestUtils ;
18- import org .bouncycastle .util .Arrays ;
1918
2019public class HashMLDSASigner
2120 implements Signer
2221{
2322 private static final byte [] EMPTY_CONTEXT = new byte [0 ];
24-
25- private MLDSAPrivateKeyParameters privKey ;
23+
2624 private MLDSAPublicKeyParameters pubKey ;
25+ private MLDSAPrivateKeyParameters privKey ;
26+ private SecureRandom random ;
2727
2828 private MLDSAEngine engine ;
29- private SecureRandom random ;
3029 private Digest digest ;
31- private byte [] digestOidEncoding ;
30+ private byte [] digestOIDEncoding ;
3231
3332 public HashMLDSASigner ()
3433 {
35- this .digest = new SHA512Digest ();
3634 }
3735
3836 public void init (boolean forSigning , CipherParameters param )
3937 {
40- byte [] ctx ;
41-
38+ byte [] ctx = EMPTY_CONTEXT ;
4239 if (param instanceof ParametersWithContext )
4340 {
44- ctx = ((ParametersWithContext )param ).getContext ();
45- param = ((ParametersWithContext )param ).getParameters ();
41+ ParametersWithContext withContext = (ParametersWithContext )param ;
42+ ctx = withContext .getContext ();
43+ param = withContext .getParameters ();
4644
4745 if (ctx .length > 255 )
4846 {
4947 throw new IllegalArgumentException ("context too long" );
5048 }
5149 }
52- else
53- {
54- ctx = EMPTY_CONTEXT ;
55- }
5650
51+ MLDSAParameters parameters ;
5752 if (forSigning )
5853 {
54+ pubKey = null ;
55+
5956 if (param instanceof ParametersWithRandom )
6057 {
61- privKey = (MLDSAPrivateKeyParameters )((ParametersWithRandom )param ).getParameters ();
62- random = ((ParametersWithRandom )param ).getRandom ();
58+ ParametersWithRandom withRandom = (ParametersWithRandom )param ;
59+ privKey = (MLDSAPrivateKeyParameters )withRandom .getParameters ();
60+ random = withRandom .getRandom ();
6361 }
6462 else
6563 {
6664 privKey = (MLDSAPrivateKeyParameters )param ;
6765 random = null ;
6866 }
6967
70- engine = privKey .getParameters ().getEngine (this .random );
68+ parameters = privKey .getParameters ();
69+ engine = parameters .getEngine (random );
7170
7271 engine .initSign (privKey .tr , true , ctx );
73-
74- initDigest (privKey );
7572 }
7673 else
7774 {
7875 pubKey = (MLDSAPublicKeyParameters )param ;
76+ privKey = null ;
77+ random = null ;
7978
80- engine = pubKey .getParameters ().getEngine (this .random );
81-
82- engine .initVerify (pubKey .rho , pubKey .t1 , true , ctx );
79+ parameters = pubKey .getParameters ();
80+ engine = parameters .getEngine (null );
8381
84- initDigest (pubKey );
82+ engine . initVerify (pubKey . rho , pubKey . t1 , true , ctx );
8583 }
8684
87- reset ( );
85+ initDigest ( parameters );
8886 }
8987
90- private void initDigest (MLDSAKeyParameters key )
88+ private void initDigest (MLDSAParameters parameters )
9189 {
92- if (key .getParameters ().isPreHash ())
93- {
94- digest = key .getParameters ().createDigest ();
95- }
90+ digest = createDigest (parameters );
9691
9792 ASN1ObjectIdentifier oid = DigestUtils .getDigestOid (digest .getAlgorithmName ());
9893 try
9994 {
100- digestOidEncoding = oid .getEncoded (ASN1Encoding .DER );
95+ digestOIDEncoding = oid .getEncoded (ASN1Encoding .DER );
10196 }
10297 catch (IOException e )
10398 {
@@ -110,69 +105,75 @@ public void update(byte b)
110105 digest .update (b );
111106 }
112107
113- @ Override
114108 public void update (byte [] in , int off , int len )
115109 {
116110 digest .update (in , off , len );
117111 }
118112
119- @ Override
120113 public byte [] generateSignature () throws CryptoException , DataLengthException
121114 {
122- SHAKEDigest msgDigest = engine . getShake256Digest ();
115+ SHAKEDigest msgDigest = finishPreHash ();
123116
124117 byte [] rnd = new byte [MLDSAEngine .RndBytes ];
125118 if (random != null )
126119 {
127120 random .nextBytes (rnd );
128121 }
129122
130- byte [] hash = new byte [digest .getDigestSize ()];
131- digest .doFinal (hash , 0 );
132-
133- byte [] ds_message = Arrays .concatenate (digestOidEncoding , hash );
134-
135- msgDigest .update (ds_message , 0 , ds_message .length );
136-
137123 return engine .generateSignature (msgDigest , privKey .rho , privKey .k , privKey .t0 , privKey .s1 , privKey .s2 , rnd );
138124 }
139125
140- @ Override
141126 public boolean verifySignature (byte [] signature )
142127 {
143- SHAKEDigest msgDigest = engine .getShake256Digest ();
144- byte [] hash = new byte [digest .getDigestSize ()];
145-
146- digest .doFinal (hash , 0 );
147-
148- byte [] ds_message = Arrays .concatenate (digestOidEncoding , hash );
149-
150- msgDigest .update (ds_message , 0 , ds_message .length );
128+ SHAKEDigest msgDigest = finishPreHash ();
151129
152130 return engine .verifyInternal (signature , signature .length , msgDigest , pubKey .rho , pubKey .t1 );
153131 }
154132
155133 /**
156134 * reset the internal state
157135 */
158- @ Override
159136 public void reset ()
160137 {
161138 digest .reset ();
162139 }
163140
141+ private SHAKEDigest finishPreHash ()
142+ {
143+ byte [] hash = new byte [digest .getDigestSize ()];
144+ digest .doFinal (hash , 0 );
145+
146+ SHAKEDigest msgDigest = engine .getShake256Digest ();
147+ // TODO It should be possible to include digestOIDEncoding in the memo'ed digest
148+ msgDigest .update (digestOIDEncoding , 0 , digestOIDEncoding .length );
149+ msgDigest .update (hash , 0 , hash .length );
150+ return msgDigest ;
151+ }
152+
164153// TODO: these are probably no longer correct and also need to be marked as protected
165- // public byte[] internalGenerateSignature(byte[] message, byte[] random)
154+ // protected byte[] internalGenerateSignature(byte[] message, byte[] random)
166155// {
167- // MLDSAEngine engine = privKey.getParameters().getEngine(this. random);
156+ // MLDSAEngine engine = privKey.getParameters().getEngine(random);
168157//
169158// return engine.signInternal(message, message.length, privKey.rho, privKey.k, privKey.t0, privKey.s1, privKey.s2, random);
170159// }
171160//
172- // public boolean internalVerifySignature(byte[] message, byte[] signature)
161+ // protected boolean internalVerifySignature(byte[] message, byte[] signature)
173162// {
174163// MLDSAEngine engine = pubKey.getParameters().getEngine(random);
175164//
176165// return engine.verifyInternal(signature, signature.length, message, message.length, pubKey.rho, pubKey.t1);
177166// }
167+
168+ private static Digest createDigest (MLDSAParameters parameters )
169+ {
170+ switch (parameters .getType ())
171+ {
172+ case MLDSAParameters .TYPE_PURE :
173+ case MLDSAParameters .TYPE_SHA2_512 :
174+ return new SHA512Digest ();
175+ default :
176+ throw new IllegalArgumentException ("unknown parameters type" );
177+ }
178+ }
178179}
0 commit comments