Skip to content

Commit cbecef3

Browse files
committed
moved to mldsa from dilithium (choke, sob, sob...)
upgraded composite signatures to FIPS definitions.
1 parent 55d71b3 commit cbecef3

36 files changed

+2888
-196
lines changed

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

Lines changed: 576 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.bouncycastle.pqc.crypto.mldsa;
2+
3+
import java.security.SecureRandom;
4+
5+
import org.bouncycastle.crypto.KeyGenerationParameters;
6+
7+
public class MLDSAKeyGenerationParameters
8+
extends KeyGenerationParameters
9+
{
10+
private final MLDSAParameters params;
11+
12+
public MLDSAKeyGenerationParameters(
13+
SecureRandom random,
14+
MLDSAParameters dilithiumParameters)
15+
{
16+
super(random, 256);
17+
this.params = dilithiumParameters;
18+
}
19+
20+
public MLDSAParameters getParameters()
21+
{
22+
return params;
23+
}
24+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package org.bouncycastle.pqc.crypto.mldsa;
2+
3+
import java.security.SecureRandom;
4+
5+
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
6+
import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
7+
import org.bouncycastle.crypto.KeyGenerationParameters;
8+
9+
public class MLDSAKeyPairGenerator
10+
implements AsymmetricCipherKeyPairGenerator
11+
{
12+
private MLDSAParameters dilithiumParams;
13+
14+
private SecureRandom random;
15+
16+
private void initialize(
17+
KeyGenerationParameters param)
18+
{
19+
this.dilithiumParams = ((MLDSAKeyGenerationParameters)param).getParameters();
20+
this.random = param.getRandom();
21+
22+
}
23+
24+
private AsymmetricCipherKeyPair genKeyPair()
25+
{
26+
MLDSAEngine engine = dilithiumParams.getEngine(random);
27+
28+
byte[][] keyPair = engine.generateKeyPair();
29+
// System.out.println("pk gen = ");
30+
// Helper.printByteArray(keyPair[0]);
31+
32+
MLDSAPublicKeyParameters pubKey = new MLDSAPublicKeyParameters(dilithiumParams, keyPair[0], keyPair[6]);
33+
MLDSAPrivateKeyParameters privKey = new MLDSAPrivateKeyParameters(dilithiumParams, keyPair[0], keyPair[1], keyPair[2], keyPair[3], keyPair[4], keyPair[5], keyPair[6]);
34+
35+
return new AsymmetricCipherKeyPair(pubKey, privKey);
36+
}
37+
38+
public void init(KeyGenerationParameters param)
39+
{
40+
this.initialize(param);
41+
}
42+
43+
public AsymmetricCipherKeyPair generateKeyPair()
44+
{
45+
return genKeyPair();
46+
}
47+
public AsymmetricCipherKeyPair internalGenerateKeyPair(byte[] seed)
48+
{
49+
MLDSAEngine engine = dilithiumParams.getEngine(random);
50+
51+
byte[][] keyPair = engine.generateKeyPairInternal(seed);
52+
// System.out.println("pk gen = ");
53+
// Helper.printByteArray(keyPair[0]);
54+
55+
MLDSAPublicKeyParameters pubKey = new MLDSAPublicKeyParameters(dilithiumParams, keyPair[0], keyPair[6]);
56+
MLDSAPrivateKeyParameters privKey = new MLDSAPrivateKeyParameters(dilithiumParams, keyPair[0], keyPair[1], keyPair[2], keyPair[3], keyPair[4], keyPair[5], keyPair[6]);
57+
58+
return new AsymmetricCipherKeyPair(pubKey, privKey);
59+
}
60+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.bouncycastle.pqc.crypto.mldsa;
2+
3+
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
4+
5+
public class MLDSAKeyParameters
6+
extends AsymmetricKeyParameter
7+
{
8+
private final MLDSAParameters params;
9+
10+
public MLDSAKeyParameters(
11+
boolean isPrivate,
12+
MLDSAParameters params)
13+
{
14+
super(isPrivate);
15+
this.params = params;
16+
}
17+
18+
public MLDSAParameters getParameters()
19+
{
20+
return params;
21+
}
22+
23+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package org.bouncycastle.pqc.crypto.mldsa;
2+
3+
import java.security.SecureRandom;
4+
5+
public class MLDSAParameters
6+
{
7+
public static final MLDSAParameters ml_dsa_44 = new MLDSAParameters("ml-dsa-44", 2);
8+
public static final MLDSAParameters ml_dsa_65 = new MLDSAParameters("ml-dsa-65", 3);
9+
public static final MLDSAParameters ml_dsa_87 = new MLDSAParameters("ml-dsa-87", 5);
10+
11+
private final int k;
12+
private final String name;
13+
14+
private MLDSAParameters(String name, int k)
15+
{
16+
this.name = name;
17+
this.k = k;
18+
}
19+
20+
MLDSAEngine getEngine(SecureRandom random)
21+
{
22+
return new MLDSAEngine(k, random);
23+
}
24+
25+
public String getName()
26+
{
27+
return name;
28+
}
29+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package org.bouncycastle.pqc.crypto.mldsa;
2+
3+
import org.bouncycastle.util.Arrays;
4+
5+
public class MLDSAPrivateKeyParameters
6+
extends MLDSAKeyParameters
7+
{
8+
final byte[] rho;
9+
final byte[] k;
10+
final byte[] tr;
11+
final byte[] s1;
12+
final byte[] s2;
13+
final byte[] t0;
14+
15+
private final byte[] t1;
16+
17+
public MLDSAPrivateKeyParameters(MLDSAParameters params, byte[] rho, byte[] K, byte[] tr, byte[] s1, byte[] s2, byte[] t0, byte[] t1)
18+
{
19+
super(true, params);
20+
this.rho = Arrays.clone(rho);
21+
this.k = Arrays.clone(K);
22+
this.tr = Arrays.clone(tr);
23+
this.s1 = Arrays.clone(s1);
24+
this.s2 = Arrays.clone(s2);
25+
this.t0 = Arrays.clone(t0);
26+
this.t1 = Arrays.clone(t1);
27+
}
28+
29+
public MLDSAPrivateKeyParameters(MLDSAParameters params, byte[] encoding, MLDSAPublicKeyParameters pubKey)
30+
{
31+
super(true, params);
32+
33+
MLDSAEngine eng = params.getEngine(null);
34+
int index = 0;
35+
this.rho = Arrays.copyOfRange(encoding, 0, MLDSAEngine.SeedBytes); index += MLDSAEngine.SeedBytes;
36+
this.k = Arrays.copyOfRange(encoding, index, index + MLDSAEngine.SeedBytes); index += MLDSAEngine.SeedBytes;
37+
this.tr = Arrays.copyOfRange(encoding, index, index + MLDSAEngine.TrBytes); index += MLDSAEngine.TrBytes;
38+
int delta = eng.getDilithiumL() * eng.getDilithiumPolyEtaPackedBytes();
39+
this.s1 = Arrays.copyOfRange(encoding, index, index + delta); index += delta;
40+
delta = eng.getDilithiumK() * eng.getDilithiumPolyEtaPackedBytes();
41+
this.s2 = Arrays.copyOfRange(encoding, index, index + delta); index += delta;
42+
delta = eng.getDilithiumK() * MLDSAEngine.DilithiumPolyT0PackedBytes;
43+
this.t0 = Arrays.copyOfRange(encoding, index, index + delta); index += delta;
44+
45+
if (pubKey != null)
46+
{
47+
this.t1 = pubKey.getT1();
48+
}
49+
else
50+
{
51+
this.t1 = null;
52+
}
53+
}
54+
55+
public byte[] getEncoded()
56+
{
57+
return Arrays.concatenate(new byte[][]{ rho, k, tr, s1, s2, t0 });
58+
}
59+
60+
public byte[] getK()
61+
{
62+
return Arrays.clone(k);
63+
}
64+
65+
/** @deprecated Use {@link #getEncoded()} instead. */
66+
public byte[] getPrivateKey()
67+
{
68+
return getEncoded();
69+
}
70+
71+
public byte[] getPublicKey()
72+
{
73+
return MLDSAPublicKeyParameters.getEncoded(rho, t1);
74+
}
75+
76+
public MLDSAPublicKeyParameters getPublicKeyParameters()
77+
{
78+
return new MLDSAPublicKeyParameters(getParameters(), rho, t1);
79+
}
80+
81+
public byte[] getRho()
82+
{
83+
return Arrays.clone(rho);
84+
}
85+
86+
public byte[] getS1()
87+
{
88+
return Arrays.clone(s1);
89+
}
90+
91+
public byte[] getS2()
92+
{
93+
return Arrays.clone(s2);
94+
}
95+
96+
public byte[] getT0()
97+
{
98+
return Arrays.clone(t0);
99+
}
100+
101+
public byte[] getT1()
102+
{
103+
return Arrays.clone(t1);
104+
}
105+
106+
public byte[] getTr()
107+
{
108+
return Arrays.clone(tr);
109+
}
110+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package org.bouncycastle.pqc.crypto.mldsa;
2+
3+
import org.bouncycastle.util.Arrays;
4+
5+
public class MLDSAPublicKeyParameters
6+
extends MLDSAKeyParameters
7+
{
8+
static byte[] getEncoded(byte[] rho, byte[] t1)
9+
{
10+
return Arrays.concatenate(rho, t1);
11+
}
12+
13+
final byte[] rho;
14+
final byte[] t1;
15+
16+
public MLDSAPublicKeyParameters(MLDSAParameters params, byte[] encoding)
17+
{
18+
super(false, params);
19+
this.rho = Arrays.copyOfRange(encoding, 0, MLDSAEngine.SeedBytes);
20+
this.t1 = Arrays.copyOfRange(encoding, MLDSAEngine.SeedBytes, encoding.length);
21+
}
22+
23+
public MLDSAPublicKeyParameters(MLDSAParameters params, byte[] rho, byte[] t1)
24+
{
25+
super(false, params);
26+
this.rho = Arrays.clone(rho);
27+
this.t1 = Arrays.clone(t1);
28+
}
29+
30+
public byte[] getEncoded()
31+
{
32+
return getEncoded(rho, t1);
33+
}
34+
35+
public byte[] getRho()
36+
{
37+
return Arrays.clone(rho);
38+
}
39+
40+
public byte[] getT1()
41+
{
42+
return Arrays.clone(t1);
43+
}
44+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package org.bouncycastle.pqc.crypto.mldsa;
2+
3+
import java.security.SecureRandom;
4+
5+
import org.bouncycastle.crypto.CipherParameters;
6+
import org.bouncycastle.crypto.params.ParametersWithRandom;
7+
import org.bouncycastle.pqc.crypto.MessageSigner;
8+
9+
public class MLDSASigner
10+
implements MessageSigner
11+
{
12+
private MLDSAPrivateKeyParameters privKey;
13+
private MLDSAPublicKeyParameters pubKey;
14+
15+
private SecureRandom random;
16+
17+
public MLDSASigner()
18+
{
19+
}
20+
21+
public void init(boolean forSigning, CipherParameters param)
22+
{
23+
if (forSigning)
24+
{
25+
if (param instanceof ParametersWithRandom)
26+
{
27+
privKey = (MLDSAPrivateKeyParameters)((ParametersWithRandom)param).getParameters();
28+
random = ((ParametersWithRandom)param).getRandom();
29+
}
30+
else
31+
{
32+
privKey = (MLDSAPrivateKeyParameters)param;
33+
random = null;
34+
}
35+
}
36+
else
37+
{
38+
pubKey = (MLDSAPublicKeyParameters)param;
39+
}
40+
}
41+
42+
public byte[] generateSignature(byte[] message)
43+
{
44+
MLDSAEngine engine = privKey.getParameters().getEngine(random);
45+
46+
return engine.sign(message, message.length, privKey.rho, privKey.k, privKey.tr, privKey.t0, privKey.s1, privKey.s2);
47+
}
48+
public byte[] internalGenerateSignature(byte[] message, byte[] random)
49+
{
50+
MLDSAEngine 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+
}
54+
55+
public boolean verifySignature(byte[] message, byte[] signature)
56+
{
57+
MLDSAEngine engine = pubKey.getParameters().getEngine(random);
58+
59+
return engine.signOpen(message, signature, signature.length, pubKey.rho, pubKey.t1);
60+
}
61+
}

0 commit comments

Comments
 (0)