Skip to content

Commit 63d00e4

Browse files
committed
removed use of PrivateKeyInfo to recover private key algorithm in CompositePrivateKey.
1 parent b8434f8 commit 63d00e4

File tree

3 files changed

+134
-5
lines changed

3 files changed

+134
-5
lines changed

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import org.bouncycastle.jcajce.interfaces.MLDSAPrivateKey;
2121
import org.bouncycastle.jcajce.provider.asymmetric.compositesignatures.CompositeIndex;
2222
import org.bouncycastle.jcajce.provider.asymmetric.compositesignatures.KeyFactorySpi;
23-
import org.bouncycastle.jcajce.provider.asymmetric.mldsa.BCMLDSAPrivateKey;
2423
import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter;
2524
import org.bouncycastle.util.Arrays;
2625
import org.bouncycastle.util.Exceptions;
@@ -136,7 +135,14 @@ private PrivateKey processKey(PrivateKey key)
136135
if (key instanceof MLDSAPrivateKey)
137136
{
138137
// TODO: we don't insist on seed but we try to accommodate it - the debate continues
139-
return ((MLDSAPrivateKey)key).getPrivateKey(true);
138+
try
139+
{
140+
return ((MLDSAPrivateKey)key).getPrivateKey(true);
141+
}
142+
catch (Exception e)
143+
{
144+
return key;
145+
}
140146
}
141147
else
142148
{
@@ -258,7 +264,7 @@ public byte[] getEncoded()
258264
{
259265
try
260266
{
261-
byte[] mldsaKey = ((BCMLDSAPrivateKey)keys.get(0)).getSeed();
267+
byte[] mldsaKey = ((MLDSAPrivateKey)keys.get(0)).getSeed();
262268
PrivateKeyInfo pki = PrivateKeyInfoFactory.createPrivateKeyInfo(PrivateKeyFactory.createKey(keys.get(1).getEncoded()));
263269
byte[] tradKey = pki.getPrivateKey().getOctets();
264270
return new PrivateKeyInfo(algorithmIdentifier, Arrays.concatenate(mldsaKey, tradKey)).getEncoded();

prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/compositesignatures/SignatureSpi.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
2626
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
27-
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
2827
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
2928
import org.bouncycastle.crypto.CryptoServicesRegistrar;
3029
import org.bouncycastle.crypto.Digest;
@@ -204,7 +203,7 @@ protected void engineInitSign(PrivateKey privateKey)
204203
}
205204
else
206205
{
207-
ASN1ObjectIdentifier sigAlgorithm = PrivateKeyInfo.getInstance(compositePrivateKey.getEncoded()).getPrivateKeyAlgorithm().getAlgorithm();
206+
ASN1ObjectIdentifier sigAlgorithm = compositePrivateKey.getAlgorithmIdentifier().getAlgorithm();
208207

209208
this.algorithm = sigAlgorithm;
210209
this.baseDigest = CompositeIndex.getDigest(sigAlgorithm);

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

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.io.ByteArrayInputStream;
55
import java.io.InputStream;
66
import java.io.InputStreamReader;
7+
import java.security.InvalidKeyException;
78
import java.security.KeyFactory;
89
import java.security.KeyPair;
910
import java.security.KeyPairGenerator;
@@ -37,6 +38,7 @@
3738
import org.bouncycastle.jcajce.CompositePrivateKey;
3839
import org.bouncycastle.jcajce.CompositePublicKey;
3940
import org.bouncycastle.jcajce.interfaces.MLDSAPrivateKey;
41+
import org.bouncycastle.jcajce.interfaces.MLDSAPublicKey;
4042
import org.bouncycastle.jcajce.provider.asymmetric.compositesignatures.CompositeIndex;
4143
import org.bouncycastle.jcajce.provider.asymmetric.mldsa.BCMLDSAPublicKey;
4244
import org.bouncycastle.jcajce.spec.CompositeSignatureSpec;
@@ -338,7 +340,70 @@ public void testMixedComposition()
338340
signature.update(Strings.toUTF8ByteArray(messageToBeSigned));
339341
TestCase.assertTrue(signature.verify(signatureValue));
340342

343+
//
344+
// as COMPOSITE on sig creation
345+
//
346+
compPublicKey = CompositePublicKey.builder(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256)
347+
.addPublicKey(mldsaKp.getPublic(), "BC")
348+
.addPublicKey(ecKp.getPublic(), "SunEC")
349+
.build();
350+
compPrivateKey = CompositePrivateKey.builder(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256)
351+
.addPrivateKey(mldsaKp.getPrivate(), "BC")
352+
.addPrivateKey(ecKp.getPrivate(), "SunEC")
353+
.build();
354+
355+
signature = Signature.getInstance("COMPOSITE", "BC");
356+
357+
signature.initSign(compPriv);
358+
signature.update(Strings.toUTF8ByteArray(messageToBeSigned));
359+
signatureValue = signature.sign();
341360

361+
signature = Signature.getInstance(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256.getId(), "BC");
362+
signature.initVerify(compPub);
363+
signature.update(Strings.toUTF8ByteArray(messageToBeSigned));
364+
TestCase.assertTrue(signature.verify(signatureValue));
365+
}
366+
367+
public void testMixedCompositionHSMStyle()
368+
throws Exception
369+
{
370+
if (Security.getProvider("SunEC") == null)
371+
{
372+
return;
373+
}
374+
KeyPairGenerator mldsaKpGen = KeyPairGenerator.getInstance("ML-DSA", "BC");
375+
376+
mldsaKpGen.initialize(MLDSAParameterSpec.ml_dsa_44);
377+
378+
KeyPair mldsaKp = mldsaKpGen.generateKeyPair();
379+
380+
KeyPairGenerator ecKpGen = KeyPairGenerator.getInstance("EC", "SunEC");
381+
382+
ecKpGen.initialize(new ECGenParameterSpec("secp256r1"));
383+
384+
KeyPair ecKp = ecKpGen.generateKeyPair();
385+
386+
CompositePublicKey compPublicKey = CompositePublicKey.builder(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256)
387+
.addPublicKey(mldsaKp.getPublic(), "BC")
388+
.addPublicKey(ecKp.getPublic(), "SunEC")
389+
.build();
390+
CompositePrivateKey compPrivateKey = CompositePrivateKey.builder(BCObjectIdentifiers.id_MLDSA44_ECDSA_P256_SHA256)
391+
.addPrivateKey(new ProxyHSMPrivateKey((MLDSAPrivateKey)mldsaKp.getPrivate()), "BC")
392+
.addPrivateKey(ecKp.getPrivate(), "SunEC")
393+
.build();
394+
395+
Signature signature = Signature.getInstance("COMPOSITE", "BC");
396+
397+
try
398+
{
399+
signature.initSign(compPrivateKey);
400+
fail("proxy HSM key did not fail with BC");
401+
}
402+
catch (InvalidKeyException e)
403+
{
404+
// we want to make sure it got at least as far as passing key to ML-DSA implementation
405+
assertEquals("unknown private key passed to ML-DSA", e.getMessage());
406+
}
342407
}
343408

344409
public void testMixedCompositionWithNull()
@@ -808,4 +873,63 @@ private static String extractString(String json, String key)
808873

809874
return json.substring(start, end).replace("\\\"", "\"");
810875
}
876+
877+
private static class ProxyHSMPrivateKey
878+
implements MLDSAPrivateKey
879+
{
880+
private final MLDSAPrivateKey privateKey;
881+
882+
ProxyHSMPrivateKey(MLDSAPrivateKey privateKey)
883+
{
884+
this.privateKey = privateKey;
885+
}
886+
887+
@Override
888+
public String getAlgorithm()
889+
{
890+
return privateKey.getAlgorithm();
891+
}
892+
893+
@Override
894+
public String getFormat()
895+
{
896+
throw new IllegalStateException("getFormat() called");
897+
}
898+
899+
@Override
900+
public byte[] getEncoded()
901+
{
902+
throw new IllegalStateException("getEncoded() called");
903+
}
904+
905+
@Override
906+
public MLDSAParameterSpec getParameterSpec()
907+
{
908+
return privateKey.getParameterSpec();
909+
}
910+
911+
@Override
912+
public MLDSAPublicKey getPublicKey()
913+
{
914+
return privateKey.getPublicKey();
915+
}
916+
917+
@Override
918+
public byte[] getPrivateData()
919+
{
920+
throw new IllegalStateException("getPrivateData() called");
921+
}
922+
923+
@Override
924+
public byte[] getSeed()
925+
{
926+
throw new IllegalStateException("getSeed() called");
927+
}
928+
929+
@Override
930+
public MLDSAPrivateKey getPrivateKey(boolean preferSeedOnly)
931+
{
932+
throw new IllegalStateException("getPrivateKey() called");
933+
}
934+
}
811935
}

0 commit comments

Comments
 (0)