Skip to content

Commit 843a99a

Browse files
committed
updated composite key private key format.
1 parent 968f305 commit 843a99a

File tree

4 files changed

+130
-8
lines changed

4 files changed

+130
-8
lines changed

pkix/src/test/java/org/bouncycastle/openssl/test/CompositeKeyTest.java

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,82 @@ public void testRSAAndECCompositeSignedDataGen()
451451
//doOutput("/tmp/comp_cms_1.pem", sWrt.toString());
452452
}
453453

454+
public void testMLDSA44andP256()
455+
throws Exception
456+
{
457+
//
458+
// set up the keys
459+
//
460+
KeyPairGenerator ecKpg = KeyPairGenerator.getInstance("EC", "BC");
461+
462+
ecKpg.initialize(new ECNamedCurveGenParameterSpec("P-256"));
463+
464+
KeyPair ecKp = ecKpg.generateKeyPair();
465+
466+
PrivateKey ecPriv = ecKp.getPrivate();
467+
PublicKey ecPub = ecKp.getPublic();
468+
469+
KeyPairGenerator rmldsaKpg = KeyPairGenerator.getInstance("ML-DSA-44", "BC");
470+
471+
KeyPair mldsaKp = rmldsaKpg.generateKeyPair();
472+
473+
PrivateKey mldsaPriv = mldsaKp.getPrivate();
474+
PublicKey mldsaPub = mldsaKp.getPublic();
475+
476+
CompositePrivateKey mlecPriv = new CompositePrivateKey(mldsaPriv, ecPriv);
477+
478+
// JcaPEMWriter pWrt = new JcaPEMWriter(new FileWriter("/tmp/mldsa44_ec_p256_priv.pem"));
479+
//
480+
// pWrt.writeObject(mlecPriv);
481+
//
482+
// pWrt.close();
483+
//
484+
// CompositePublicKey mlecPub = new CompositePublicKey(mldsaPub, ecPub);
485+
//
486+
// pWrt = new JcaPEMWriter(new FileWriter("/tmp/mldsa44_ec_p256_pub.pem"));
487+
//
488+
// pWrt.writeObject(mlecPub);
489+
//
490+
// pWrt.close();
491+
}
492+
493+
public void testMLDSA87andEd448()
494+
throws Exception
495+
{
496+
//
497+
// set up the keys
498+
//
499+
KeyPairGenerator ecKpg = KeyPairGenerator.getInstance("ED448", "BC");
500+
501+
KeyPair ecKp = ecKpg.generateKeyPair();
502+
503+
PrivateKey ecPriv = ecKp.getPrivate();
504+
PublicKey ecPub = ecKp.getPublic();
505+
506+
KeyPairGenerator rmldsaKpg = KeyPairGenerator.getInstance("ML-DSA-87", "BC");
507+
508+
KeyPair mldsaKp = rmldsaKpg.generateKeyPair();
509+
510+
PrivateKey mldsaPriv = mldsaKp.getPrivate();
511+
PublicKey mldsaPub = mldsaKp.getPublic();
512+
513+
CompositePrivateKey mlecPriv = new CompositePrivateKey(mldsaPriv, ecPriv);
514+
515+
// JcaPEMWriter pWrt = new JcaPEMWriter(new FileWriter("/tmp/mldsa87_ed448_priv.pem"));
516+
//
517+
// pWrt.writeObject(mlecPriv);
518+
//
519+
// pWrt.close();
520+
//
521+
// CompositePublicKey mlecPub = new CompositePublicKey(mldsaPub, ecPub);
522+
//
523+
// pWrt = new JcaPEMWriter(new FileWriter("/tmp/mldsa87_ed448_pub.pem"));
524+
//
525+
// pWrt.writeObject(mlecPub);
526+
//
527+
// pWrt.close();
528+
}
529+
454530
private static void doOutput(String fileName, String contents)
455531
throws IOException
456532
{

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,14 @@ public byte[] getEncoded()
134134

135135
for (int i = 0; i < keys.size(); i++)
136136
{
137-
v.add(PrivateKeyInfo.getInstance(keys.get(i).getEncoded()));
137+
ASN1EncodableVector kV = new ASN1EncodableVector();
138+
139+
PrivateKeyInfo info = PrivateKeyInfo.getInstance(keys.get(i).getEncoded());
140+
141+
kV.add(info.getPrivateKeyAlgorithm());
142+
kV.add(info.getPrivateKey());
143+
144+
v.add(new DERSequence(kV));
138145
}
139146

140147
try

prov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/COMPOSITE.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
import java.util.HashMap;
99
import java.util.Map;
1010

11+
import org.bouncycastle.asn1.ASN1EncodableVector;
1112
import org.bouncycastle.asn1.ASN1Sequence;
13+
import org.bouncycastle.asn1.DERSequence;
1214
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
1315
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
1416
import org.bouncycastle.internal.asn1.misc.MiscObjectIdentifiers;
@@ -89,10 +91,28 @@ public PrivateKey generatePrivate(PrivateKeyInfo keyInfo)
8991

9092
for (int i = 0; i != keySeq.size(); i++)
9193
{
92-
PrivateKeyInfo privInfo = PrivateKeyInfo.getInstance(keySeq.getObjectAt(i));
94+
ASN1Sequence kSeq = ASN1Sequence.getInstance(keySeq.getObjectAt(i));
9395

94-
privKeys[i] = provider.getKeyInfoConverter(
95-
privInfo.getPrivateKeyAlgorithm().getAlgorithm()).generatePrivate(privInfo);
96+
if (kSeq.size() == 2)
97+
{
98+
ASN1EncodableVector v = new ASN1EncodableVector(2);
99+
100+
v.add(keyInfo.getVersion());
101+
v.add(kSeq.getObjectAt(0));
102+
v.add(kSeq.getObjectAt(1));
103+
104+
PrivateKeyInfo privInfo = PrivateKeyInfo.getInstance(new DERSequence(v));
105+
106+
privKeys[i] = provider.getKeyInfoConverter(
107+
privInfo.getPrivateKeyAlgorithm().getAlgorithm()).generatePrivate(privInfo);
108+
}
109+
else
110+
{
111+
PrivateKeyInfo privInfo = PrivateKeyInfo.getInstance(kSeq);
112+
113+
privKeys[i] = provider.getKeyInfoConverter(
114+
privInfo.getPrivateKeyAlgorithm().getAlgorithm()).generatePrivate(privInfo);
115+
}
96116
}
97117

98118
return new CompositePrivateKey(privKeys);

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

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.List;
1717

1818
import org.bouncycastle.asn1.ASN1BitString;
19+
import org.bouncycastle.asn1.ASN1EncodableVector;
1920
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
2021
import org.bouncycastle.asn1.ASN1Sequence;
2122
import org.bouncycastle.asn1.DERBitString;
@@ -100,10 +101,28 @@ public PrivateKey generatePrivate(PrivateKeyInfo keyInfo)
100101
PrivateKey[] privateKeys = new PrivateKey[seq.size()];
101102
for (int i = 0; i < seq.size(); i++)
102103
{
103-
// We assume each component is of type OneAsymmetricKey (PrivateKeyInfo) as defined by the draft RFC
104-
// and use the component key factory to decode the component key from PrivateKeyInfo.
105-
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(PrivateKeyInfo.getInstance(seq.getObjectAt(i)).getEncoded());
106-
privateKeys[i] = factories.get(i).generatePrivate(keySpec);
104+
ASN1Sequence keySeq = ASN1Sequence.getInstance(seq.getObjectAt(i));
105+
106+
// new format
107+
if (keySeq.size() == 2)
108+
{
109+
ASN1EncodableVector v = new ASN1EncodableVector(2);
110+
111+
v.add(keyInfo.getVersion());
112+
v.add(keySeq.getObjectAt(0));
113+
v.add(keySeq.getObjectAt(1));
114+
115+
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(
116+
PrivateKeyInfo.getInstance(new DERSequence(v)).getEncoded());
117+
privateKeys[i] = factories.get(i).generatePrivate(keySpec);
118+
}
119+
else // old format
120+
{
121+
// We assume each component is of type OneAsymmetricKey (PrivateKeyInfo) as defined by the draft RFC
122+
// and use the component key factory to decode the component key from PrivateKeyInfo.
123+
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(PrivateKeyInfo.getInstance(keySeq).getEncoded());
124+
privateKeys[i] = factories.get(i).generatePrivate(keySpec);
125+
}
107126
}
108127
return new CompositePrivateKey(keyIdentifier, privateKeys);
109128
}

0 commit comments

Comments
 (0)