Skip to content

Commit 08d1f20

Browse files
author
royb
committed
enabled domain separation to mldsa keygen
disabled old KAT test, added acvp sample vector
1 parent f33ab6e commit 08d1f20

File tree

4 files changed

+431
-159
lines changed

4 files changed

+431
-159
lines changed

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

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.security.SecureRandom;
44

5+
import org.bouncycastle.crypto.Digest;
56
import org.bouncycastle.crypto.digests.SHAKEDigest;
67
import org.bouncycastle.util.Arrays;
78

@@ -244,24 +245,28 @@ else if (this.DilithiumGamma1 == (1 << 19))
244245
}
245246
}
246247

247-
public byte[][] generateKeyPair()
248+
//Internal functions are deterministic. No randomness is sampled inside them
249+
public byte[][] generateKeyPairInternal(byte[] seed)
248250
{
249-
byte[] seedBuf = new byte[SeedBytes];
250251
byte[] buf = new byte[2 * SeedBytes + CrhBytes];
251252
byte[] tr = new byte[TrBytes];
252253

253254
byte[] rho = new byte[SeedBytes],
254-
rhoPrime = new byte[CrhBytes],
255-
key = new byte[SeedBytes];
255+
rhoPrime = new byte[CrhBytes],
256+
key = new byte[SeedBytes];
256257

257258
PolyVecMatrix aMatrix = new PolyVecMatrix(this);
258259

259260
PolyVecL s1 = new PolyVecL(this), s1hat;
260261
PolyVecK s2 = new PolyVecK(this), t1 = new PolyVecK(this), t0 = new PolyVecK(this);
261262

262-
random.nextBytes(seedBuf);
263263

264-
shake256Digest.update(seedBuf, 0, SeedBytes);
264+
265+
shake256Digest.update(seed, 0, SeedBytes);
266+
267+
//Domain separation
268+
shake256Digest.update((byte)DilithiumK);
269+
shake256Digest.update((byte)DilithiumL);
265270

266271
shake256Digest.doFinal(buf, 0, 2 * SeedBytes + CrhBytes);
267272
// System.out.print("buf = ");
@@ -315,11 +320,11 @@ public byte[][] generateKeyPair()
315320
shake256Digest.doFinal(tr, 0, TrBytes);
316321

317322
byte[][] sk = Packing.packSecretKey(rho, tr, key, t0, s1, s2, this);
318-
323+
319324
return new byte[][]{ sk[0], sk[1], sk[2], sk[3], sk[4], sk[5], encT1};
320325
}
321326

322-
public byte[] signSignature(byte[] msg, int msglen, byte[] rho, byte[] key, byte[] tr, byte[] t0Enc, byte[] s1Enc, byte[] s2Enc)
327+
public byte[] signSignatureInternal(byte[] msg, int msglen, byte[] rho, byte[] key, byte[] tr, byte[] t0Enc, byte[] s1Enc, byte[] s2Enc, byte[] rnd)
323328
{
324329
int n;
325330
byte[] outSig = new byte[CryptoBytes + msglen];
@@ -336,11 +341,7 @@ public byte[] signSignature(byte[] msg, int msglen, byte[] rho, byte[] key, byte
336341
this.shake256Digest.update(msg, 0, msglen);
337342
this.shake256Digest.doFinal(mu, 0, CrhBytes);
338343

339-
byte[] rnd = new byte[RndBytes];
340-
if (random != null)
341-
{
342-
random.nextBytes(rnd);
343-
}
344+
344345

345346
byte[] keyMu = Arrays.copyOf(key, SeedBytes + RndBytes + CrhBytes);
346347
System.arraycopy(rnd, 0, keyMu, SeedBytes, RndBytes);
@@ -424,17 +425,12 @@ public byte[] signSignature(byte[] msg, int msglen, byte[] rho, byte[] key, byte
424425
return null;
425426
}
426427

427-
public byte[] sign(byte[] msg, int mlen, byte[] rho, byte[] key, byte[] tr, byte[] t0, byte[] s1, byte[] s2)
428-
{
429-
return signSignature(msg, mlen, rho, key, tr, t0, s1, s2);
430-
}
431-
432-
public boolean signVerify(byte[] sig, int siglen, byte[] msg, int msglen, byte[] rho, byte[] encT1)
428+
public boolean signVerifyInternal(byte[] sig, int siglen, byte[] msg, int msglen, byte[] rho, byte[] encT1)
433429
{
434430
byte[] buf,
435-
mu = new byte[CrhBytes],
436-
c,
437-
c2 = new byte[DilithiumCTilde];
431+
mu = new byte[CrhBytes],
432+
c,
433+
c2 = new byte[DilithiumCTilde];
438434
Poly cp = new Poly(this);
439435
PolyVecMatrix aMatrix = new PolyVecMatrix(this);
440436
PolyVecL z = new PolyVecL(this);
@@ -540,8 +536,50 @@ public boolean signVerify(byte[] sig, int siglen, byte[] msg, int msglen, byte[]
540536
return Arrays.constantTimeAreEqual(c, c2);
541537
}
542538

539+
540+
541+
public byte[][] generateKeyPair()
542+
{
543+
byte[] seedBuf = new byte[SeedBytes];
544+
random.nextBytes(seedBuf);
545+
return generateKeyPairInternal(seedBuf);
546+
547+
}
548+
549+
public byte[] signSignature(byte[] msg, int msglen, byte[] rho, byte[] key, byte[] tr, byte[] t0Enc, byte[] s1Enc, byte[] s2Enc)
550+
{
551+
byte[] rnd = new byte[RndBytes];
552+
if (random != null)
553+
{
554+
random.nextBytes(rnd);
555+
}
556+
return signSignatureInternal(msg, msglen, rho, key, tr, t0Enc, s1Enc, s2Enc, rnd);
557+
}
558+
559+
public byte[] sign(byte[] msg, int mlen, byte[] rho, byte[] key, byte[] tr, byte[] t0, byte[] s1, byte[] s2)
560+
{
561+
return signSignature(msg, mlen, rho, key, tr, t0, s1, s2);
562+
}
563+
564+
public boolean signVerify(byte[] sig, int siglen, byte[] msg, int msglen, byte[] rho, byte[] encT1)
565+
{
566+
//TODO: add domain separation
567+
// M' <- BytesToBits( IntegerToBytes(0, 1) || IntegerToBytes(|ctx|, 1) || ctx ) || M
568+
return signVerifyInternal(sig, siglen, msg, msglen, rho, encT1);
569+
}
570+
543571
public boolean signOpen(byte[] msg, byte[] signedMsg, int signedMsglen, byte[] rho, byte[] t1)
544572
{
573+
//TODO: add domain separation
574+
// M' <- BytesToBits( IntegerToBytes(0, 1) || IntegerToBytes(|ctx|, 1) || ctx ) || M
545575
return signVerify(signedMsg, signedMsglen, msg, msg.length, rho, t1);
546576
}
577+
578+
// HashML-DSA
579+
//TODO: Generate a "pre-hash" ML-DSA signature
580+
// public byte[] hashSign(byte[] sk, byte[] message, byte[] ctx, Digest ph) {}
581+
//TODO: Verify a pre-hash HashML-DSA signature
582+
// public boolean hashVerify(byte[] pk, byte[] message, byte[] sig) {}
583+
584+
547585
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,17 @@ public AsymmetricCipherKeyPair generateKeyPair()
4444
{
4545
return genKeyPair();
4646
}
47+
public AsymmetricCipherKeyPair internalGenerateKeyPair(byte[] seed)
48+
{
49+
DilithiumEngine engine = dilithiumParams.getEngine(random);
50+
51+
byte[][] keyPair = engine.generateKeyPairInternal(seed);
52+
// System.out.println("pk gen = ");
53+
// Helper.printByteArray(keyPair[0]);
54+
55+
DilithiumPublicKeyParameters pubKey = new DilithiumPublicKeyParameters(dilithiumParams, keyPair[0], keyPair[6]);
56+
DilithiumPrivateKeyParameters privKey = new DilithiumPrivateKeyParameters(dilithiumParams, keyPair[0], keyPair[1], keyPair[2], keyPair[3], keyPair[4], keyPair[5], keyPair[6]);
57+
58+
return new AsymmetricCipherKeyPair(pubKey, privKey);
59+
}
4760
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ public byte[] generateSignature(byte[] message)
4545

4646
return engine.sign(message, message.length, privKey.rho, privKey.k, privKey.tr, privKey.t0, privKey.s1, privKey.s2);
4747
}
48+
public byte[] internalGenerateSignature(byte[] message, byte[] random)
49+
{
50+
DilithiumEngine engine = privKey.getParameters().getEngine(this.random);
51+
52+
return engine.signSignatureInternal(message, message.length, privKey.rho, privKey.k, privKey.tr, privKey.t0, privKey.s1, privKey.s2, random);
53+
}
4854

4955
public boolean verifySignature(byte[] message, byte[] signature)
5056
{

0 commit comments

Comments
 (0)