Skip to content

Commit c28c616

Browse files
committed
corrected private key encoding.
1 parent 38a7b97 commit c28c616

File tree

2 files changed

+149
-20
lines changed

2 files changed

+149
-20
lines changed

prov/src/main/java/org/bouncycastle/jcajce/CompositePrivateKey.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.bouncycastle.crypto.util.PrivateKeyFactory;
1616
import org.bouncycastle.crypto.util.PrivateKeyInfoFactory;
1717
import org.bouncycastle.internal.asn1.misc.MiscObjectIdentifiers;
18+
import org.bouncycastle.jcajce.interfaces.MLDSAPrivateKey;
1819
import org.bouncycastle.jcajce.provider.asymmetric.compositesignatures.CompositeIndex;
1920
import org.bouncycastle.jcajce.provider.asymmetric.compositesignatures.KeyFactorySpi;
2021
import org.bouncycastle.jcajce.provider.asymmetric.mldsa.BCMLDSAPrivateKey;
@@ -68,7 +69,15 @@ public CompositePrivateKey(AlgorithmIdentifier algorithmIdentifier, PrivateKey..
6869
List<PrivateKey> keyList = new ArrayList<PrivateKey>(keys.length);
6970
for (int i = 0; i < keys.length; i++)
7071
{
71-
keyList.add(keys[i]);
72+
if (keys[i] instanceof MLDSAPrivateKey)
73+
{
74+
// TODO: we don't insist on seed but we try to accommodate it - the debate continues
75+
keyList.add(((MLDSAPrivateKey)keys[i]).getPrivateKey(true));
76+
}
77+
else
78+
{
79+
keyList.add(keys[i]);
80+
}
7281
}
7382
this.keys = Collections.unmodifiableList(keyList);
7483
}
@@ -147,7 +156,7 @@ public byte[] getEncoded()
147156
byte[] mldsaKey = ((BCMLDSAPrivateKey)keys.get(0)).getSeed();
148157
PrivateKeyInfo pki = PrivateKeyInfoFactory.createPrivateKeyInfo(PrivateKeyFactory.createKey(keys.get(1).getEncoded()));
149158
byte[] tradKey = pki.getPrivateKey().getOctets();
150-
return Arrays.concatenate(mldsaKey, tradKey);
159+
return new PrivateKeyInfo(algorithmIdentifier, Arrays.concatenate(mldsaKey, tradKey)).getEncoded();
151160
}
152161
catch (IOException e)
153162
{

prov/src/test/java/org/bouncycastle/jcajce/provider/test/CompositeSignaturesTest.java

Lines changed: 138 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
import java.security.Signature;
1414
import java.security.cert.CertificateFactory;
1515
import java.security.cert.X509Certificate;
16+
import java.security.interfaces.RSAPrivateKey;
17+
import java.security.interfaces.RSAPublicKey;
18+
import java.security.spec.ECGenParameterSpec;
1619
import java.security.spec.PKCS8EncodedKeySpec;
1720
import java.security.spec.X509EncodedKeySpec;
1821
import java.util.ArrayList;
@@ -23,16 +26,19 @@
2326

2427
import junit.framework.TestCase;
2528
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
29+
import org.bouncycastle.asn1.ASN1Primitive;
2630
import org.bouncycastle.asn1.DEROctetString;
31+
import org.bouncycastle.asn1.bc.BCObjectIdentifiers;
2732
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
33+
import org.bouncycastle.asn1.util.ASN1Dump;
2834
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
2935
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
36+
import org.bouncycastle.internal.asn1.misc.MiscObjectIdentifiers;
3037
import org.bouncycastle.jcajce.CompositePrivateKey;
3138
import org.bouncycastle.jcajce.CompositePublicKey;
3239
import org.bouncycastle.jcajce.interfaces.MLDSAPrivateKey;
3340
import org.bouncycastle.jcajce.provider.asymmetric.compositesignatures.CompositeIndex;
3441
import org.bouncycastle.jcajce.provider.asymmetric.mldsa.BCMLDSAPublicKey;
35-
import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey;
3642
import org.bouncycastle.jcajce.spec.ContextParameterSpec;
3743
import org.bouncycastle.jcajce.spec.MLDSAParameterSpec;
3844
import org.bouncycastle.jcajce.spec.MLDSAPrivateKeySpec;
@@ -122,26 +128,72 @@ public void testKeyPairGeneration()
122128
CompositePublicKey compositePublicKey = (CompositePublicKey)keyPair.getPublic();
123129
CompositePrivateKey compositePrivateKey = (CompositePrivateKey)keyPair.getPrivate();
124130

125-
String firstPublicKeyAlgorithm = Strings.toUpperCase(compositePublicKey.getPublicKeys().get(0).getAlgorithm());
126-
String secondPublicKeyAlgorithm = Strings.toUpperCase(compositePublicKey.getPublicKeys().get(1).getAlgorithm());
127-
String firstPrivateKeyAlgorithm = Strings.toUpperCase(compositePrivateKey.getPrivateKeys().get(0).getAlgorithm());
128-
String secondPrivateKeyAlgorithm = Strings.toUpperCase(compositePrivateKey.getPrivateKeys().get(1).getAlgorithm());
129-
130-
BCRSAPublicKey rsaPublicKey = null;
131-
BCRSAPublicKey rsaPrivateKey = null;
132-
131+
ASN1ObjectIdentifier compAlg = compositePrivateKey.getAlgorithmIdentifier().getAlgorithm();
132+
if (compAlg.equals(BCObjectIdentifiers.id_MLDSA44_RSA2048_PKCS15_SHA256))
133+
{
134+
check_RSA_Composite("ML-DSA-44", 2048, compositePublicKey, compositePrivateKey);
135+
}
136+
else if (compAlg.equals(BCObjectIdentifiers.id_MLDSA65_RSA3072_PKCS15_SHA512))
137+
{
138+
check_RSA_Composite("ML-DSA-65", 3072, compositePublicKey, compositePrivateKey);
139+
}
140+
else if (compAlg.equals(BCObjectIdentifiers.id_MLDSA87_RSA3072_PSS_SHA512))
141+
{
142+
check_RSA_Composite("ML-DSA-87", 3072, compositePublicKey, compositePrivateKey);
143+
}
144+
else if (compAlg.equals(BCObjectIdentifiers.id_MLDSA87_RSA4096_PSS_SHA512))
145+
{
146+
check_RSA_Composite("ML-DSA-87", 4096, compositePublicKey, compositePrivateKey);
147+
}
148+
else if (compAlg.equals(BCObjectIdentifiers.id_MLDSA44_Ed25519_SHA512))
149+
{
150+
check_EdDSA_Composite("ML-DSA-44", "Ed25519", compositePublicKey, compositePrivateKey);
151+
}
152+
else if (compAlg.equals(BCObjectIdentifiers.id_MLDSA65_Ed25519_SHA512))
153+
{
154+
check_EdDSA_Composite("ML-DSA-65", "Ed25519", compositePublicKey, compositePrivateKey);
155+
}
156+
else if (compAlg.equals(BCObjectIdentifiers.id_MLDSA87_Ed448_SHAKE256))
157+
{
158+
check_EdDSA_Composite("ML-DSA-87", "Ed448", compositePublicKey, compositePrivateKey);
159+
}
160+
else if (compAlg.equals(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256))
161+
{
162+
check_ECDSA_Composite("ML-DSA-44", compositePublicKey, compositePrivateKey);
163+
}
164+
else if (compAlg.equals(BCObjectIdentifiers.id_MLDSA65_ECDSA_P256_SHA512))
165+
{
166+
check_ECDSA_Composite("ML-DSA-65", compositePublicKey, compositePrivateKey);
167+
}
168+
else if (compAlg.equals(BCObjectIdentifiers.id_MLDSA65_ECDSA_P384_SHA512))
169+
{
170+
check_ECDSA_Composite("ML-DSA-65", compositePublicKey, compositePrivateKey);
171+
}
172+
else if (compAlg.equals(MiscObjectIdentifiers.id_MLDSA65_ECDSA_P384_SHA384))
173+
{
174+
check_ECDSA_Composite("ML-DSA-65", compositePublicKey, compositePrivateKey);
175+
}
176+
else if (compAlg.equals(BCObjectIdentifiers.id_MLDSA87_ECDSA_brainpoolP384r1_SHA512))
177+
{
178+
check_ECDSA_Composite("ML-DSA-87", compositePublicKey, compositePrivateKey);
179+
}
180+
else if (compAlg.equals(BCObjectIdentifiers.id_MLDSA87_ECDSA_P384_SHA512))
181+
{
182+
check_ECDSA_Composite("ML-DSA-87", compositePublicKey, compositePrivateKey);
183+
}
184+
else if (compAlg.equals(BCObjectIdentifiers.id_MLDSA87_ECDSA_P521_SHA512))
185+
{
186+
check_ECDSA_Composite("ML-DSA-87", compositePublicKey, compositePrivateKey);
187+
}
188+
else
189+
{
190+
System.out.println(CompositeIndex.getAlgorithmName(compAlg));
191+
}
133192
// switch (CompositeSignaturesConstants.ASN1IdentifierCompositeNameMap.get(new ASN1ObjectIdentifier(oid)))
134193
// {
135194
// case MLDSA44_RSA2048_PSS_SHA256:
136195
// case MLDSA44_RSA2048_PKCS15_SHA256:
137-
// TestCase.assertEquals("ML-DSA-44", firstPublicKeyAlgorithm);
138-
// TestCase.assertEquals("ML-DSA-44", firstPrivateKeyAlgorithm);
139-
// TestCase.assertEquals("RSA", secondPublicKeyAlgorithm);
140-
// TestCase.assertEquals("RSA", secondPrivateKeyAlgorithm);
141-
// rsaPublicKey = (BCRSAPublicKey)compositePublicKey.getPublicKeys().get(1);
142-
// rsaPrivateKey = (BCRSAPublicKey)compositePublicKey.getPublicKeys().get(1);
143-
// TestCase.assertEquals(2048, rsaPublicKey.getModulus().bitLength());
144-
// TestCase.assertEquals(2048, rsaPrivateKey.getModulus().bitLength());
196+
//
145197
// break;
146198
// case MLDSA44_Ed25519_SHA512:
147199
// TestCase.assertEquals("ML-DSA-44", firstPublicKeyAlgorithm);
@@ -174,7 +226,7 @@ public void testKeyPairGeneration()
174226
// TestCase.assertEquals("ED25519", secondPrivateKeyAlgorithm);
175227
// break;
176228
// case MLDSA65_ECDSA_P256_SHA512:
177-
// case MLDSA65_ECDSA_brainpoolP256r1_SHA512: ompositeK
229+
// case MLDSA65_ECDSA_brainpoolP256r1_SHA512:
178230
// TestCase.assertEquals("ML-DSA-65", firstPublicKeyAlgorithm);
179231
// TestCase.assertEquals("ML-DSA-65", firstPrivateKeyAlgorithm);
180232
// TestCase.assertEquals("ECDSA", secondPublicKeyAlgorithm);
@@ -200,6 +252,74 @@ public void testKeyPairGeneration()
200252
}
201253
}
202254

255+
private void check_RSA_Composite(String firstAlg, int rsaKeySize, CompositePublicKey compPub, CompositePrivateKey compPriv)
256+
{
257+
TestCase.assertEquals(firstAlg, compPub.getPublicKeys().get(0).getAlgorithm());
258+
TestCase.assertEquals("RSA", compPub.getPublicKeys().get(1).getAlgorithm());
259+
RSAPublicKey rsaPublicKey = (RSAPublicKey)compPub.getPublicKeys().get(1);
260+
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)compPriv.getPrivateKeys().get(1);
261+
TestCase.assertEquals(rsaKeySize, rsaPublicKey.getModulus().bitLength());
262+
TestCase.assertEquals(rsaKeySize, rsaPrivateKey.getModulus().bitLength());
263+
}
264+
265+
private void check_EdDSA_Composite(String firstAlg, String edDSAAlg, CompositePublicKey compPub, CompositePrivateKey compPriv)
266+
{
267+
TestCase.assertEquals(firstAlg, compPub.getPublicKeys().get(0).getAlgorithm());
268+
TestCase.assertEquals(edDSAAlg, compPub.getPublicKeys().get(1).getAlgorithm());
269+
TestCase.assertEquals(firstAlg, compPriv.getPrivateKeys().get(0).getAlgorithm());
270+
TestCase.assertEquals(edDSAAlg, compPriv.getPrivateKeys().get(1).getAlgorithm());
271+
}
272+
273+
private void check_ECDSA_Composite(String firstAlg, CompositePublicKey compPub, CompositePrivateKey compPriv)
274+
{
275+
TestCase.assertEquals(firstAlg, compPub.getPublicKeys().get(0).getAlgorithm());
276+
TestCase.assertEquals("EC", compPub.getPublicKeys().get(1).getAlgorithm());
277+
TestCase.assertEquals(firstAlg, compPriv.getPrivateKeys().get(0).getAlgorithm());
278+
TestCase.assertEquals("EC", compPriv.getPrivateKeys().get(1).getAlgorithm());
279+
}
280+
281+
public void testSelfComposition()
282+
throws Exception
283+
{
284+
KeyPairGenerator mldsaKpGen = KeyPairGenerator.getInstance("ML-DSA", "BC");
285+
286+
mldsaKpGen.initialize(MLDSAParameterSpec.ml_dsa_44);
287+
288+
KeyPair mldsaKp = mldsaKpGen.generateKeyPair();
289+
290+
KeyPairGenerator ecKpGen = KeyPairGenerator.getInstance("EC", "BC");
291+
292+
ecKpGen.initialize(new ECGenParameterSpec("P-256"));
293+
294+
KeyPair ecKp = ecKpGen.generateKeyPair();
295+
296+
CompositePublicKey compPublicKey = new CompositePublicKey(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256, mldsaKp.getPublic(), ecKp.getPublic());
297+
CompositePrivateKey compPrivateKey = new CompositePrivateKey(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256, mldsaKp.getPrivate(), ecKp.getPrivate());
298+
299+
Signature signature = Signature.getInstance(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256.getId(), "BC");
300+
signature.initSign(compPrivateKey);
301+
signature.update(Strings.toUTF8ByteArray(messageToBeSigned));
302+
byte[] signatureValue = signature.sign();
303+
304+
signature.initVerify(compPublicKey);
305+
signature.update(Strings.toUTF8ByteArray(messageToBeSigned));
306+
TestCase.assertTrue(signature.verify(signatureValue));
307+
308+
KeyFactory compFact = KeyFactory.getInstance(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256.getId(), "BC");
309+
System.err.println(ASN1Dump.dumpAsString(ASN1Primitive.fromByteArray(compPrivateKey.getEncoded())));
310+
PrivateKey compPriv = compFact.generatePrivate(new PKCS8EncodedKeySpec(compPrivateKey.getEncoded()));
311+
PublicKey compPub = compFact.generatePublic(new X509EncodedKeySpec(compPublicKey.getEncoded()));
312+
313+
signature.initSign(compPriv);
314+
signature.update(Strings.toUTF8ByteArray(messageToBeSigned));
315+
signatureValue = signature.sign();
316+
317+
signature.initVerify(compPub);
318+
signature.update(Strings.toUTF8ByteArray(messageToBeSigned));
319+
TestCase.assertTrue(signature.verify(signatureValue));
320+
321+
}
322+
203323
public void testSigningAndVerificationInternal()
204324
throws Exception
205325
{

0 commit comments

Comments
 (0)