Skip to content

Commit 0b6d399

Browse files
committed
fixed checkstyle issue, initial experiment with ML-DSA seed files
1 parent de1894d commit 0b6d399

File tree

8 files changed

+143
-9
lines changed

8 files changed

+143
-9
lines changed

core/src/main/java/org/bouncycastle/asn1/bc/BCObjectIdentifiers.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,4 +429,18 @@ public interface BCObjectIdentifiers
429429
ASN1ObjectIdentifier hqc128 = pqc_kem_hqc.branch("1");
430430
ASN1ObjectIdentifier hqc192 = pqc_kem_hqc.branch("2");
431431
ASN1ObjectIdentifier hqc256 = pqc_kem_hqc.branch("3");
432+
433+
/**
434+
* ML-KEM/ML-DSA seed parameters algorithms - temporary
435+
*
436+
*/
437+
//TODO: delete before release
438+
ASN1ObjectIdentifier id_id_alg_seed = bc.branch("10");
439+
440+
ASN1ObjectIdentifier id_id_alg_ml_dsa_44_seed = id_id_alg_seed.branch("1");
441+
ASN1ObjectIdentifier id_id_alg_ml_dsa_65_seed = id_id_alg_seed.branch("2");
442+
ASN1ObjectIdentifier id_id_alg_ml_dsa_87_seed = id_id_alg_seed.branch("3");
443+
ASN1ObjectIdentifier id_id_alg_ml_kem_512_seed = id_id_alg_seed.branch("4");
444+
ASN1ObjectIdentifier id_id_alg_ml_kem_768_seed = id_id_alg_seed.branch("5");
445+
ASN1ObjectIdentifier id_id_alg_ml_kem_1024_seed = id_id_alg_seed.branch("6");
432446
}

core/src/main/java/org/bouncycastle/pqc/crypto/util/Utils.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,9 @@ class Utils
279279
mldsaParams.put(NISTObjectIdentifiers.id_ml_dsa_44, MLDSAParameters.ml_dsa_44);
280280
mldsaParams.put(NISTObjectIdentifiers.id_ml_dsa_65, MLDSAParameters.ml_dsa_65);
281281
mldsaParams.put(NISTObjectIdentifiers.id_ml_dsa_87, MLDSAParameters.ml_dsa_87);
282+
mldsaParams.put(BCObjectIdentifiers.id_id_alg_ml_dsa_44_seed, MLDSAParameters.ml_dsa_44);
283+
mldsaParams.put(BCObjectIdentifiers.id_id_alg_ml_dsa_65_seed, MLDSAParameters.ml_dsa_65);
284+
mldsaParams.put(BCObjectIdentifiers.id_id_alg_ml_dsa_87_seed, MLDSAParameters.ml_dsa_87);
282285
mldsaParams.put(NISTObjectIdentifiers.id_hash_ml_dsa_44_with_sha512, MLDSAParameters.ml_dsa_44_with_sha512);
283286
mldsaParams.put(NISTObjectIdentifiers.id_hash_ml_dsa_65_with_sha512, MLDSAParameters.ml_dsa_65_with_sha512);
284287
mldsaParams.put(NISTObjectIdentifiers.id_hash_ml_dsa_87_with_sha512, MLDSAParameters.ml_dsa_87_with_sha512);

prov/src/main/java/org/bouncycastle/jcajce/interfaces/MLDSAPrivateKey.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,12 @@ public interface MLDSAPrivateKey
2525
* @return the seed for the private key, null if not available.
2626
*/
2727
byte[] getSeed();
28+
29+
/**
30+
* Return the encoding of the key or an encoding of its key generation parameters (the seed).
31+
*
32+
* @param asKeyGenParams return a key gen parameters structure.
33+
* @return a PKCS#8 of the private key encoding, or a PKCS#8 of the seed.
34+
*/
35+
byte[] getEncoded(boolean asKeyGenParams);
2836
}

prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/mldsa/BCMLDSAPrivateKey.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,21 @@ public final String getAlgorithm()
9191
return algorithm;
9292
}
9393

94+
public byte[] getEncoded(boolean asKeyGenParams)
95+
{
96+
if (asKeyGenParams)
97+
{
98+
byte[] seed = params.getSeed();
99+
if (seed == null)
100+
{
101+
return null;
102+
}
103+
return KeyUtil.getEncodedPrivateKeyInfo(getParameterSpec(), seed, attributes);
104+
}
105+
106+
return getEncoded();
107+
}
108+
94109
public byte[] getEncoded()
95110
{
96111
if (encoding == null)

prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/mldsa/MLDSAKeyFactorySpi.java

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.util.Set;
1414

1515
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
16+
import org.bouncycastle.asn1.bc.BCObjectIdentifiers;
1617
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
1718
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
1819
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
@@ -44,14 +45,22 @@ public class MLDSAKeyFactorySpi
4445
hashKeyOids.add(NISTObjectIdentifiers.id_hash_ml_dsa_87_with_sha512);
4546
}
4647

48+
private final boolean isHashOnly;
49+
4750
public MLDSAKeyFactorySpi(Set<ASN1ObjectIdentifier> keyOids)
4851
{
4952
super(keyOids);
53+
54+
this.isHashOnly = false;
5055
}
5156

52-
public MLDSAKeyFactorySpi(ASN1ObjectIdentifier keyOid)
57+
public MLDSAKeyFactorySpi(ASN1ObjectIdentifier keyOid, ASN1ObjectIdentifier seedOid)
5358
{
54-
super(keyOid);
59+
super(setOf(keyOid, seedOid));
60+
61+
this.isHashOnly = (keyOid.equals(NISTObjectIdentifiers.id_hash_ml_dsa_44_with_sha512)
62+
|| keyOid.equals(NISTObjectIdentifiers.id_hash_ml_dsa_65_with_sha512)
63+
|| keyOid.equals(NISTObjectIdentifiers.id_hash_ml_dsa_87_with_sha512));
5564
}
5665

5766
public final KeySpec engineGetKeySpec(Key key, Class keySpec)
@@ -165,7 +174,37 @@ public PublicKey engineGeneratePublic(
165174
public PrivateKey generatePrivate(PrivateKeyInfo keyInfo)
166175
throws IOException
167176
{
168-
return new BCMLDSAPrivateKey(keyInfo);
177+
BCMLDSAPrivateKey key = new BCMLDSAPrivateKey(keyInfo);
178+
179+
if (!isHashOnly || (key.getAlgorithm().indexOf("WITH") > 0))
180+
{
181+
return key;
182+
}
183+
184+
// keyfactory for hash-only, convert key to hash-only.
185+
MLDSAPrivateKeyParameters kParams = key.getKeyParams();
186+
MLDSAParameters mldsaParameters = null;
187+
if (kParams.getParameters().equals(MLDSAParameters.ml_dsa_44))
188+
{
189+
mldsaParameters = MLDSAParameters.ml_dsa_44_with_sha512;
190+
}
191+
else if (kParams.getParameters().equals(MLDSAParameters.ml_dsa_65))
192+
{
193+
mldsaParameters = MLDSAParameters.ml_dsa_65_with_sha512;
194+
}
195+
else if (kParams.getParameters().equals(MLDSAParameters.ml_dsa_87))
196+
{
197+
mldsaParameters = MLDSAParameters.ml_dsa_87_with_sha512;
198+
}
199+
else
200+
{
201+
throw new IllegalStateException("unknown ML-DSA parameters");
202+
}
203+
204+
MLDSAPrivateKeyParameters hkParams = new MLDSAPrivateKeyParameters(
205+
mldsaParameters, kParams.getRho(), kParams.getK(), kParams.getTr(), kParams.getS1(), kParams.getS2(), kParams.getT0(), kParams.getT1(), kParams.getSeed());
206+
207+
return new BCMLDSAPrivateKey(hkParams);
169208
}
170209

171210
public PublicKey generatePublic(SubjectPublicKeyInfo keyInfo)
@@ -188,7 +227,7 @@ public static class MLDSA44
188227
{
189228
public MLDSA44()
190229
{
191-
super(NISTObjectIdentifiers.id_ml_dsa_44);
230+
super(NISTObjectIdentifiers.id_ml_dsa_44, BCObjectIdentifiers.id_id_alg_ml_dsa_44_seed);
192231
}
193232
}
194233

@@ -197,7 +236,7 @@ public static class MLDSA65
197236
{
198237
public MLDSA65()
199238
{
200-
super(NISTObjectIdentifiers.id_ml_dsa_65);
239+
super(NISTObjectIdentifiers.id_ml_dsa_65, BCObjectIdentifiers.id_id_alg_ml_dsa_65_seed);
201240
}
202241
}
203242

@@ -206,7 +245,7 @@ public static class MLDSA87
206245
{
207246
public MLDSA87()
208247
{
209-
super(NISTObjectIdentifiers.id_ml_dsa_87);
248+
super(NISTObjectIdentifiers.id_ml_dsa_87, BCObjectIdentifiers.id_id_alg_ml_dsa_87_seed);
210249
}
211250
}
212251

@@ -224,7 +263,7 @@ public static class HashMLDSA44
224263
{
225264
public HashMLDSA44()
226265
{
227-
super(NISTObjectIdentifiers.id_hash_ml_dsa_44_with_sha512);
266+
super(NISTObjectIdentifiers.id_hash_ml_dsa_44_with_sha512, BCObjectIdentifiers.id_id_alg_ml_dsa_44_seed);
228267
}
229268
}
230269

@@ -233,7 +272,7 @@ public static class HashMLDSA65
233272
{
234273
public HashMLDSA65()
235274
{
236-
super(NISTObjectIdentifiers.id_hash_ml_dsa_65_with_sha512);
275+
super(NISTObjectIdentifiers.id_hash_ml_dsa_65_with_sha512, BCObjectIdentifiers.id_id_alg_ml_dsa_65_seed);
237276
}
238277
}
239278

@@ -242,7 +281,7 @@ public static class HashMLDSA87
242281
{
243282
public HashMLDSA87()
244283
{
245-
super(NISTObjectIdentifiers.id_hash_ml_dsa_87_with_sha512);
284+
super(NISTObjectIdentifiers.id_hash_ml_dsa_87_with_sha512, BCObjectIdentifiers.id_id_alg_ml_dsa_87_seed);
246285
}
247286
}
248287
}

prov/src/main/java/org/bouncycastle/pqc/jcajce/provider/util/BaseKeyFactorySpi.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.security.spec.KeySpec;
88
import java.security.spec.PKCS8EncodedKeySpec;
99
import java.security.spec.X509EncodedKeySpec;
10+
import java.util.HashSet;
1011
import java.util.Set;
1112

1213
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
@@ -33,6 +34,16 @@ protected BaseKeyFactorySpi(ASN1ObjectIdentifier keyOid)
3334
this.keyOids = null;
3435
}
3536

37+
protected static Set setOf(ASN1ObjectIdentifier oid1, ASN1ObjectIdentifier oid2)
38+
{
39+
Set hashSet = new HashSet(2);
40+
41+
hashSet.add(oid1);
42+
hashSet.add(oid2);
43+
44+
return hashSet;
45+
}
46+
3647
public PrivateKey engineGeneratePrivate(KeySpec keySpec)
3748
throws InvalidKeySpecException
3849
{

prov/src/main/java/org/bouncycastle/pqc/jcajce/provider/util/KeyUtil.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package org.bouncycastle.pqc.jcajce.provider.util;
22

3+
import java.security.spec.AlgorithmParameterSpec;
4+
35
import org.bouncycastle.asn1.ASN1Encodable;
46
import org.bouncycastle.asn1.ASN1Encoding;
57
import org.bouncycastle.asn1.ASN1Set;
8+
import org.bouncycastle.asn1.bc.BCObjectIdentifiers;
69
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
710
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
811
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
912
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
13+
import org.bouncycastle.jcajce.spec.MLDSAParameterSpec;
1014
import org.bouncycastle.pqc.crypto.util.PrivateKeyInfoFactory;
1115
import org.bouncycastle.pqc.crypto.util.SubjectPublicKeyInfoFactory;
1216

@@ -91,6 +95,45 @@ public static byte[] getEncodedPrivateKeyInfo(PrivateKeyInfo info)
9195
}
9296
}
9397

98+
public static byte[] getEncodedPrivateKeyInfo(AlgorithmParameterSpec paramSpec, byte[] seed, ASN1Set attributes)
99+
{
100+
byte[] enc = null;
101+
102+
try
103+
{
104+
if (paramSpec instanceof MLDSAParameterSpec)
105+
{
106+
String name = ((MLDSAParameterSpec)paramSpec).getName();
107+
if (name.equals(MLDSAParameterSpec.ml_dsa_44.getName()) || name.equals(MLDSAParameterSpec.ml_dsa_44_with_sha512.getName()))
108+
{
109+
enc = new PrivateKeyInfo(new AlgorithmIdentifier(BCObjectIdentifiers.id_id_alg_ml_dsa_44_seed), seed, attributes).getEncoded();
110+
}
111+
else if (name.equals(MLDSAParameterSpec.ml_dsa_65.getName()) || name.equals(MLDSAParameterSpec.ml_dsa_65_with_sha512.getName()))
112+
{
113+
enc = new PrivateKeyInfo(new AlgorithmIdentifier(BCObjectIdentifiers.id_id_alg_ml_dsa_65_seed), seed, attributes).getEncoded();
114+
}
115+
else if (name.equals(MLDSAParameterSpec.ml_dsa_87.getName()) || name.equals(MLDSAParameterSpec.ml_dsa_87_with_sha512.getName()))
116+
{
117+
enc = new PrivateKeyInfo(new AlgorithmIdentifier(BCObjectIdentifiers.id_id_alg_ml_dsa_87_seed), seed, attributes).getEncoded();
118+
}
119+
else
120+
{
121+
throw new IllegalStateException("unknown ML-DSA algorithm");
122+
}
123+
}
124+
}
125+
catch (IllegalStateException e)
126+
{
127+
throw e;
128+
}
129+
catch (Exception e)
130+
{
131+
return null;
132+
}
133+
134+
return enc;
135+
}
136+
94137
public static byte[] getEncodedPrivateKeyInfo(AsymmetricKeyParameter privateKey, ASN1Set attributes)
95138
{
96139
if (!privateKey.isPrivate())

prov/src/test/java/org/bouncycastle/pqc/jcajce/provider/test/MLDSATest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ private void tryKeyFact(KeyFactory kFact, KeyPair kpValid, KeyPair kpInvalid, St
124124
throws Exception
125125
{
126126
kFact.generatePrivate(new PKCS8EncodedKeySpec(kpValid.getPrivate().getEncoded()));
127+
kFact.generatePrivate(new PKCS8EncodedKeySpec(((MLDSAPrivateKey)kpValid.getPrivate()).getEncoded(true)));
127128
kFact.generatePublic(new X509EncodedKeySpec(kpValid.getPublic().getEncoded()));
128129

129130
try

0 commit comments

Comments
 (0)