Skip to content

Commit db6aac9

Browse files
committed
Refactoring in ML-DSA, SLH-DSA
- FIx signer inits to set all fields
1 parent 19145af commit db6aac9

File tree

12 files changed

+280
-236
lines changed

12 files changed

+280
-236
lines changed

core/src/main/java/org/bouncycastle/crypto/params/ParametersWithContext.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,33 @@ public ParametersWithContext(
1313
CipherParameters parameters,
1414
byte[] context)
1515
{
16+
if (context == null)
17+
{
18+
throw new NullPointerException("'context' cannot be null");
19+
}
20+
1621
this.parameters = parameters;
1722
this.context = Arrays.clone(context);
1823
}
1924

25+
public void copyContextTo(byte[] buf, int off, int len)
26+
{
27+
if (context.length != len)
28+
throw new IllegalArgumentException("len");
29+
30+
System.arraycopy(context, 0, buf, off, len);
31+
}
32+
2033
public byte[] getContext()
2134
{
2235
return Arrays.clone(context);
2336
}
2437

38+
public int getContextLength()
39+
{
40+
return context.length;
41+
}
42+
2543
public CipherParameters getParameters()
2644
{
2745
return parameters;

core/src/main/java/org/bouncycastle/pqc/crypto/crystals/dilithium/DilithiumEngine.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@
22

33
import java.security.SecureRandom;
44

5-
import org.bouncycastle.crypto.Digest;
65
import org.bouncycastle.crypto.digests.SHAKEDigest;
76
import org.bouncycastle.util.Arrays;
87

98
class DilithiumEngine
109
{
1110
private final SecureRandom random;
1211

13-
private final SHAKEDigest shake128Digest = new SHAKEDigest(128);
1412
private final SHAKEDigest shake256Digest = new SHAKEDigest(256);
1513

1614
public final static int DilithiumN = 256;
@@ -152,11 +150,6 @@ SHAKEDigest getShake256Digest()
152150
return this.shake256Digest;
153151
}
154152

155-
SHAKEDigest getShake128Digest()
156-
{
157-
return this.shake128Digest;
158-
}
159-
160153
DilithiumEngine(int mode, SecureRandom random, boolean usingAes)
161154
{
162155
this.DilithiumMode = mode;

core/src/main/java/org/bouncycastle/pqc/crypto/mldsa/HashMLDSASigner.java

Lines changed: 54 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -15,89 +15,84 @@
1515
import org.bouncycastle.crypto.params.ParametersWithContext;
1616
import org.bouncycastle.crypto.params.ParametersWithRandom;
1717
import org.bouncycastle.pqc.crypto.DigestUtils;
18-
import org.bouncycastle.util.Arrays;
1918

2019
public 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
}

core/src/main/java/org/bouncycastle/pqc/crypto/mldsa/MLDSAEngine.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ class MLDSAEngine
99
{
1010
private final SecureRandom random;
1111

12-
private final SHAKEDigest shake128Digest = new SHAKEDigest(128);
1312
private final SHAKEDigest shake256Digest = new SHAKEDigest(256);
1413

1514
public final static int DilithiumN = 256;
@@ -311,12 +310,12 @@ SHAKEDigest getShake256Digest()
311310

312311
void initSign(byte[] tr, boolean isPreHash, byte[] ctx)
313312
{
314-
this.shake256Digest.update(tr, 0, TrBytes);
313+
shake256Digest.update(tr, 0, TrBytes);
315314
if (ctx != null)
316315
{
317-
this.shake256Digest.update((isPreHash) ? (byte)1 : (byte)0);
318-
this.shake256Digest.update((byte)ctx.length);
319-
this.shake256Digest.update(ctx, 0, ctx.length);
316+
shake256Digest.update(isPreHash ? (byte)1 : (byte)0);
317+
shake256Digest.update((byte)ctx.length);
318+
shake256Digest.update(ctx, 0, ctx.length);
320319
}
321320
}
322321

@@ -327,16 +326,13 @@ void initVerify(byte[] rho, byte[] encT1, boolean isPreHash, byte[] ctx)
327326
shake256Digest.update(rho, 0, rho.length);
328327
shake256Digest.update(encT1, 0, encT1.length);
329328
shake256Digest.doFinal(mu, 0, TrBytes);
330-
// System.out.println("mu before = ");
331-
// Helper.printByteArray(mu);
332329

333330
shake256Digest.update(mu, 0, TrBytes);
334-
335331
if (ctx != null)
336332
{
337-
this.shake256Digest.update((isPreHash) ? (byte)1 : (byte)0);
338-
this.shake256Digest.update((byte)ctx.length);
339-
this.shake256Digest.update(ctx, 0, ctx.length);
333+
shake256Digest.update(isPreHash ? (byte)1 : (byte)0);
334+
shake256Digest.update((byte)ctx.length);
335+
shake256Digest.update(ctx, 0, ctx.length);
340336
}
341337
}
342338

core/src/main/java/org/bouncycastle/pqc/crypto/mldsa/MLDSAKeyPairGenerator.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,22 @@
99
public class MLDSAKeyPairGenerator
1010
implements AsymmetricCipherKeyPairGenerator
1111
{
12-
private MLDSAParameters dilithiumParams;
12+
private MLDSAParameters parameters;
1313
private SecureRandom random;
1414

1515
public void init(KeyGenerationParameters param)
1616
{
17-
this.dilithiumParams = ((MLDSAKeyGenerationParameters)param).getParameters();
17+
this.parameters = ((MLDSAKeyGenerationParameters)param).getParameters();
1818
this.random = param.getRandom();
1919
}
2020

2121
public AsymmetricCipherKeyPair generateKeyPair()
2222
{
23-
MLDSAEngine engine = dilithiumParams.getEngine(random);
23+
MLDSAEngine engine = parameters.getEngine(random);
2424

2525
byte[][] keyPair = engine.generateKeyPair();
26-
MLDSAPublicKeyParameters pubKey = new MLDSAPublicKeyParameters(dilithiumParams, keyPair[0], keyPair[6]);
27-
MLDSAPrivateKeyParameters privKey = new MLDSAPrivateKeyParameters(dilithiumParams, keyPair[0], keyPair[1], keyPair[2], keyPair[3], keyPair[4], keyPair[5], keyPair[6], keyPair[7]);
26+
MLDSAPublicKeyParameters pubKey = new MLDSAPublicKeyParameters(parameters, keyPair[0], keyPair[6]);
27+
MLDSAPrivateKeyParameters privKey = new MLDSAPrivateKeyParameters(parameters, keyPair[0], keyPair[1], keyPair[2], keyPair[3], keyPair[4], keyPair[5], keyPair[6], keyPair[7]);
2828

2929
return new AsymmetricCipherKeyPair(pubKey, privKey);
3030
}

core/src/main/java/org/bouncycastle/pqc/crypto/mldsa/MLDSAParameters.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

33
import java.security.SecureRandom;
44

5-
import org.bouncycastle.crypto.Digest;
6-
import org.bouncycastle.crypto.digests.SHA512Digest;
7-
85
public class MLDSAParameters
96
{
107
public static final int TYPE_PURE = 0;
@@ -38,11 +35,6 @@ public int getType()
3835
{
3936
return preHashDigest;
4037
}
41-
42-
Digest createDigest()
43-
{
44-
return preHashDigest == TYPE_PURE ? null : new SHA512Digest();
45-
}
4638

4739
MLDSAEngine getEngine(SecureRandom random)
4840
{

0 commit comments

Comments
 (0)