Skip to content

Commit 499cb95

Browse files
committed
initial refactoring to free up digest access for signature generation.
1 parent 7352222 commit 499cb95

File tree

5 files changed

+176
-74
lines changed

5 files changed

+176
-74
lines changed

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

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,18 @@
1111
import org.bouncycastle.crypto.Digest;
1212
import org.bouncycastle.crypto.Signer;
1313
import org.bouncycastle.crypto.digests.SHA512Digest;
14+
import org.bouncycastle.crypto.digests.SHAKEDigest;
1415
import org.bouncycastle.crypto.params.ParametersWithRandom;
1516
import org.bouncycastle.pqc.crypto.DigestUtils;
17+
import org.bouncycastle.util.Arrays;
1618

1719
public class HashMLDSASigner
1820
implements Signer
1921
{
2022
private MLDSAPrivateKeyParameters privKey;
2123
private MLDSAPublicKeyParameters pubKey;
2224

25+
private MLDSAEngine engine;
2326
private SecureRandom random;
2427
private Digest digest;
2528
private byte[] digestOidEncoding;
@@ -44,6 +47,16 @@ public void init(boolean forSigning, CipherParameters param)
4447
random = null;
4548
}
4649

50+
engine = privKey.getParameters().getEngine(this.random);
51+
52+
byte[] ctx = privKey.getContext();
53+
if (ctx.length > 255)
54+
{
55+
throw new IllegalArgumentException("context too long");
56+
}
57+
58+
engine.initSign(privKey.tr, true, ctx);
59+
4760
initDigest(privKey);
4861
}
4962
else
@@ -88,13 +101,7 @@ public void update(byte[] in, int off, int len)
88101
@Override
89102
public byte[] generateSignature() throws CryptoException, DataLengthException
90103
{
91-
MLDSAEngine engine = privKey.getParameters().getEngine(random);
92-
93-
byte[] ctx = privKey.getContext();
94-
if (ctx.length > 255)
95-
{
96-
throw new RuntimeException("Context too long");
97-
}
104+
SHAKEDigest msgDigest = engine.getShake256Digest();
98105

99106
byte[] rnd = new byte[MLDSAEngine.RndBytes];
100107
if (random != null)
@@ -105,14 +112,9 @@ public byte[] generateSignature() throws CryptoException, DataLengthException
105112
byte[] hash = new byte[digest.getDigestSize()];
106113
digest.doFinal(hash, 0);
107114

108-
byte[] ds_message = new byte[1 + 1 + ctx.length + + digestOidEncoding.length + hash.length];
109-
ds_message[0] = 1;
110-
ds_message[1] = (byte)ctx.length;
111-
System.arraycopy(ctx, 0, ds_message, 2, ctx.length);
112-
System.arraycopy(digestOidEncoding, 0, ds_message, 2 + ctx.length, digestOidEncoding.length);
113-
System.arraycopy(hash, 0, ds_message, 2 + ctx.length + digestOidEncoding.length, hash.length);
115+
byte[] ds_message = Arrays.concatenate(digestOidEncoding, hash);
114116

115-
return engine.signInternal(ds_message, ds_message.length, privKey.rho, privKey.k, privKey.tr, privKey.t0, privKey.s1, privKey.s2, rnd);
117+
return engine.signInternal(ds_message, ds_message.length, privKey.rho, privKey.k, privKey.t0, privKey.s1, privKey.s2, rnd);
116118
}
117119

118120
@Override
@@ -153,7 +155,7 @@ public byte[] internalGenerateSignature(byte[] message, byte[] random)
153155
{
154156
MLDSAEngine engine = privKey.getParameters().getEngine(this.random);
155157

156-
return engine.signInternal(message, message.length, privKey.rho, privKey.k, privKey.tr, privKey.t0, privKey.s1, privKey.s2, random);
158+
return engine.signInternal(message, message.length, privKey.rho, privKey.k, privKey.t0, privKey.s1, privKey.s2, random);
157159
}
158160

159161
public boolean internalVerifySignature(byte[] message, byte[] signature)

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

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ class MLDSAEngine
4949

5050
private final int PolyUniformGamma1NBlocks;
5151

52-
private final Symmetric symmetric;;
52+
private final Symmetric symmetric;
53+
;
5354

5455
protected Symmetric GetSymmetric()
5556
{
@@ -120,7 +121,7 @@ int getDilithiumOmega()
120121
{
121122
return DilithiumOmega;
122123
}
123-
124+
124125
int getDilithiumCTilde()
125126
{
126127
return DilithiumCTilde;
@@ -146,16 +147,6 @@ int getPolyUniformGamma1NBlocks()
146147
return this.PolyUniformGamma1NBlocks;
147148
}
148149

149-
SHAKEDigest getShake256Digest()
150-
{
151-
return this.shake256Digest;
152-
}
153-
154-
SHAKEDigest getShake128Digest()
155-
{
156-
return this.shake128Digest;
157-
}
158-
159150
MLDSAEngine(int mode, SecureRandom random)
160151
{
161152
this.DilithiumMode = mode;
@@ -206,7 +197,7 @@ SHAKEDigest getShake128Digest()
206197
default:
207198
throw new IllegalArgumentException("The mode " + mode + "is not supported by Crystals Dilithium!");
208199
}
209-
200+
210201
this.symmetric = new Symmetric.ShakeSymmetric();
211202

212203
this.random = random;
@@ -243,16 +234,15 @@ private byte[][] generateKeyPairInternal(byte[] seed)
243234
byte[] tr = new byte[TrBytes];
244235

245236
byte[] rho = new byte[SeedBytes],
246-
rhoPrime = new byte[CrhBytes],
247-
key = new byte[SeedBytes];
237+
rhoPrime = new byte[CrhBytes],
238+
key = new byte[SeedBytes];
248239

249240
PolyVecMatrix aMatrix = new PolyVecMatrix(this);
250241

251242
PolyVecL s1 = new PolyVecL(this), s1hat;
252243
PolyVecK s2 = new PolyVecK(this), t1 = new PolyVecK(this), t0 = new PolyVecK(this);
253244

254245

255-
256246
shake256Digest.update(seed, 0, SeedBytes);
257247

258248
//Domain separation
@@ -312,14 +302,42 @@ private byte[][] generateKeyPairInternal(byte[] seed)
312302

313303
byte[][] sk = Packing.packSecretKey(rho, tr, key, t0, s1, s2, this);
314304

315-
return new byte[][]{ sk[0], sk[1], sk[2], sk[3], sk[4], sk[5], encT1};
305+
return new byte[][]{sk[0], sk[1], sk[2], sk[3], sk[4], sk[5], encT1};
316306
}
317307

318-
public byte[] signInternal(byte[] msg, int msglen, byte[] rho, byte[] key, byte[] tr, byte[] t0Enc, byte[] s1Enc, byte[] s2Enc, byte[] rnd)
308+
SHAKEDigest getShake256Digest()
319309
{
310+
return new SHAKEDigest(shake256Digest);
311+
}
312+
void initSign(byte[] tr, boolean isPreHash, byte[] ctx)
313+
{
314+
this.shake256Digest.update(tr, 0, TrBytes);
315+
if (ctx != null)
316+
{
317+
this.shake256Digest.update((isPreHash) ? (byte)1 : (byte)0);
318+
this.shake256Digest.update((byte)ctx.length);
319+
this.shake256Digest.update(ctx, 0, ctx.length);
320+
}
321+
}
322+
323+
public byte[] signInternal(byte[] msg, int msglen, byte[] rho, byte[] key, byte[] t0Enc, byte[] s1Enc, byte[] s2Enc, byte[] rnd)
324+
{
325+
SHAKEDigest shake256 = new SHAKEDigest(shake256Digest);
326+
327+
shake256.update(msg, 0, msglen);
328+
329+
return generateSignature(shake256, rho, key, t0Enc, s1Enc, s2Enc, rnd);
330+
}
331+
332+
byte[] generateSignature(SHAKEDigest shake256Digest, byte[] rho, byte[] key, byte[] t0Enc, byte[] s1Enc, byte[] s2Enc, byte[] rnd)
333+
{
334+
byte[] mu = new byte[CrhBytes];
335+
336+
shake256Digest.doFinal(mu, 0, CrhBytes);
337+
320338
int n;
321-
byte[] outSig = new byte[CryptoBytes + msglen];
322-
byte[] mu = new byte[CrhBytes], rhoPrime = new byte[CrhBytes];
339+
byte[] outSig = new byte[CryptoBytes];
340+
byte[] rhoPrime = new byte[CrhBytes];
323341
short nonce = 0;
324342
PolyVecL s1 = new PolyVecL(this), y = new PolyVecL(this), z = new PolyVecL(this);
325343
PolyVecK t0 = new PolyVecK(this), s2 = new PolyVecK(this), w1 = new PolyVecK(this), w0 = new PolyVecK(this), h = new PolyVecK(this);
@@ -328,12 +346,6 @@ public byte[] signInternal(byte[] msg, int msglen, byte[] rho, byte[] key, byte[
328346

329347
Packing.unpackSecretKey(t0, s1, s2, t0Enc, s1Enc, s2Enc, this);
330348

331-
this.shake256Digest.update(tr, 0, TrBytes);
332-
this.shake256Digest.update(msg, 0, msglen);
333-
this.shake256Digest.doFinal(mu, 0, CrhBytes);
334-
335-
336-
337349
byte[] keyMu = Arrays.copyOf(key, SeedBytes + RndBytes + CrhBytes);
338350
System.arraycopy(rnd, 0, keyMu, SeedBytes, RndBytes);
339351
System.arraycopy(mu, 0, keyMu, SeedBytes + RndBytes, CrhBytes);
@@ -418,22 +430,21 @@ public byte[] signInternal(byte[] msg, int msglen, byte[] rho, byte[] key, byte[
418430

419431
public boolean verifyInternal(byte[] sig, int siglen, byte[] msg, int msglen, byte[] rho, byte[] encT1)
420432
{
421-
byte[] buf,
422-
mu = new byte[CrhBytes],
423-
c,
424-
c2 = new byte[DilithiumCTilde];
425-
Poly cp = new Poly(this);
426-
PolyVecMatrix aMatrix = new PolyVecMatrix(this);
427-
PolyVecL z = new PolyVecL(this);
428-
PolyVecK t1 = new PolyVecK(this), w1 = new PolyVecK(this), h = new PolyVecK(this);
429-
430433
if (siglen != CryptoBytes)
431434
{
432435
return false;
433436
}
434437

435438
// System.out.println("publickey = ");
436439
// Helper.printByteArray(publicKey);
440+
byte[] buf,
441+
mu = new byte[CrhBytes],
442+
c,
443+
c2 = new byte[DilithiumCTilde];
444+
Poly cp = new Poly(this);
445+
PolyVecMatrix aMatrix = new PolyVecMatrix(this);
446+
PolyVecL z = new PolyVecL(this);
447+
PolyVecK t1 = new PolyVecK(this), w1 = new PolyVecK(this), h = new PolyVecK(this);
437448

438449
t1 = Packing.unpackPublicKey(t1, encT1, this);
439450

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

Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,29 @@
11
package org.bouncycastle.pqc.crypto.mldsa;
22

3+
import java.io.ByteArrayOutputStream;
34
import java.security.SecureRandom;
45

56
import org.bouncycastle.crypto.CipherParameters;
7+
import org.bouncycastle.crypto.CryptoException;
8+
import org.bouncycastle.crypto.DataLengthException;
9+
import org.bouncycastle.crypto.Signer;
10+
import org.bouncycastle.crypto.digests.SHAKEDigest;
611
import org.bouncycastle.crypto.params.ParametersWithRandom;
7-
import org.bouncycastle.pqc.crypto.MessageSigner;
812

913
public class MLDSASigner
10-
implements MessageSigner
14+
implements Signer
1115
{
1216
private MLDSAPrivateKeyParameters privKey;
1317
private MLDSAPublicKeyParameters pubKey;
1418

19+
private MLDSAEngine engine;
20+
private SHAKEDigest msgDigest;
21+
1522
private SecureRandom random;
1623

24+
// TODO: temporary
25+
private ByteArrayOutputStream bOut = new ByteArrayOutputStream();
26+
1727
public MLDSASigner()
1828
{
1929
}
@@ -35,11 +45,25 @@ public void init(boolean forSigning, CipherParameters param)
3545
random = null;
3646
}
3747

48+
engine = privKey.getParameters().getEngine(this.random);
49+
50+
byte[] ctx = privKey.getContext();
51+
if (ctx.length > 255)
52+
{
53+
throw new IllegalArgumentException("context too long");
54+
}
55+
56+
engine.initSign(privKey.tr, false, ctx);
57+
58+
msgDigest = engine.getShake256Digest();
59+
3860
isPreHash = privKey.getParameters().isPreHash();
3961
}
4062
else
4163
{
4264
pubKey = (MLDSAPublicKeyParameters)param;
65+
engine = null;
66+
msgDigest = null;
4367
isPreHash = pubKey.getParameters().isPreHash();
4468
}
4569

@@ -49,39 +73,77 @@ public void init(boolean forSigning, CipherParameters param)
4973
}
5074
}
5175

52-
public byte[] generateSignature(byte[] message)
76+
public void update(byte b)
5377
{
54-
MLDSAEngine engine = privKey.getParameters().getEngine(random);
78+
if (msgDigest != null)
79+
{
80+
msgDigest.update(b);
81+
}
82+
else
83+
{
84+
bOut.write(b);
85+
}
86+
}
5587

56-
byte[] ctx = privKey.getContext();
57-
if (ctx.length > 255)
88+
public void update(byte[] in, int off, int len)
89+
{
90+
if (msgDigest != null)
5891
{
59-
throw new RuntimeException("Context too long");
92+
msgDigest.update(in, off, len);
6093
}
94+
else
95+
{
96+
bOut.write(in, off, len);
97+
}
98+
}
6199

100+
public byte[] generateSignature()
101+
throws CryptoException, DataLengthException
102+
{
62103
byte[] rnd = new byte[MLDSAEngine.RndBytes];
63104
if (random != null)
64105
{
65106
random.nextBytes(rnd);
66107
}
67108

68-
byte[] ds_message = new byte[1 + 1 + ctx.length + message.length];
69-
ds_message[0] = 0;
70-
ds_message[1] = (byte)ctx.length;
71-
System.arraycopy(ctx, 0, ds_message, 2, ctx.length);
72-
System.arraycopy(message, 0, ds_message, 2 + ctx.length, message.length);
109+
return engine.generateSignature(msgDigest, privKey.rho, privKey.k, privKey.t0, privKey.s1, privKey.s2, rnd);
110+
}
111+
112+
public boolean verifySignature(byte[] signature)
113+
{
114+
boolean isTrue = verifySignature(bOut.toByteArray(), signature);
115+
116+
bOut.reset();
117+
118+
return isTrue;
119+
}
73120

74-
return engine.signInternal(ds_message, ds_message.length, privKey.rho, privKey.k, privKey.tr, privKey.t0, privKey.s1, privKey.s2, rnd);
121+
public void reset()
122+
{
123+
bOut.reset();
124+
}
125+
126+
byte[] generateSignature(byte[] message)
127+
{
128+
byte[] rnd = new byte[MLDSAEngine.RndBytes];
129+
if (random != null)
130+
{
131+
random.nextBytes(rnd);
132+
}
133+
134+
return engine.signInternal(message, message.length, privKey.rho, privKey.k, privKey.t0, privKey.s1, privKey.s2, rnd);
75135
}
76136

77-
public byte[] internalGenerateSignature(byte[] message, byte[] random)
137+
protected byte[] internalGenerateSignature(byte[] message, byte[] random)
78138
{
79139
MLDSAEngine engine = privKey.getParameters().getEngine(this.random);
80140

81-
return engine.signInternal(message, message.length, privKey.rho, privKey.k, privKey.tr, privKey.t0, privKey.s1, privKey.s2, random);
141+
engine.initSign(privKey.tr, false, null);
142+
143+
return engine.signInternal(message, message.length, privKey.rho, privKey.k, privKey.t0, privKey.s1, privKey.s2, random);
82144
}
83145

84-
public boolean verifySignature(byte[] message, byte[] signature)
146+
boolean verifySignature(byte[] message, byte[] signature)
85147
{
86148
MLDSAEngine engine = pubKey.getParameters().getEngine(random);
87149

@@ -99,6 +161,7 @@ public boolean verifySignature(byte[] message, byte[] signature)
99161

100162
return engine.verifyInternal(signature, signature.length, ds_message, ds_message.length, pubKey.rho, pubKey.t1);
101163
}
164+
102165
public boolean internalVerifySignature(byte[] message, byte[] signature)
103166
{
104167
MLDSAEngine engine = pubKey.getParameters().getEngine(random);

0 commit comments

Comments
 (0)