Skip to content

Commit 26688ee

Browse files
ligefeiBouncycastledghgit
authored andcommitted
MLDSA Composite signature version 7+
1 parent 7a0bed7 commit 26688ee

File tree

14 files changed

+1394
-345
lines changed

14 files changed

+1394
-345
lines changed

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,43 @@ public interface BCObjectIdentifiers
365365
/** 2.16.840.1.114027.80.8.1.13 OQS_OID_MLDSA87_ed448 */
366366
ASN1ObjectIdentifier mldsa87_ed448 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.8.1.13");
367367

368+
/** 2.16.840.1.114027.80.9.1.0 id-MLDSA44-RSA2048-PSS-SHA256 */
369+
ASN1ObjectIdentifier id_MLDSA44_RSA2048_PSS_SHA256 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.0");
370+
/** 2.16.840.1.114027.80.9.1.1 id-MLDSA44-RSA2048-PKCS15-SHA256 */
371+
ASN1ObjectIdentifier id_MLDSA44_RSA2048_PKCS15_SHA256 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.1");
372+
/** 2.16.840.1.114027.80.9.1.2 id-MLDSA44-Ed25519-SHA512 */
373+
ASN1ObjectIdentifier id_MLDSA44_Ed25519_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.2");
374+
/** 2.16.840.1.114027.80.9.1.3 id-MLDSA44-ECDSA-P256-SHA256 */
375+
ASN1ObjectIdentifier id_MLDSA44_ECDSA_P256_SHA256 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.3");
376+
/** 2.16.840.1.114027.80.9.1.4 id-MLDSA65-RSA3072-PSS-SHA512 */
377+
ASN1ObjectIdentifier id_MLDSA65_RSA3072_PSS_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.4");
378+
/** 2.16.840.1.114027.80.9.1.5 id-MLDSA65-RSA3072-PKCS15-SHA512 */
379+
ASN1ObjectIdentifier id_MLDSA65_RSA3072_PKCS15_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.5");
380+
/** 2.16.840.1.114027.80.9.1.6 id-MLDSA65-RSA4096-PSS-SHA512 */
381+
ASN1ObjectIdentifier id_MLDSA65_RSA4096_PSS_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.6");
382+
/** 2.16.840.1.114027.80.9.1.7 id-MLDSA65-RSA4096-PKCS15-SHA512 */
383+
ASN1ObjectIdentifier id_MLDSA65_RSA4096_PKCS15_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.7");
384+
/** 2.16.840.1.114027.80.9.1.8 id-MLDSA65-ECDSA-P256-SHA512 */
385+
ASN1ObjectIdentifier id_MLDSA65_ECDSA_P256_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.8");
386+
/** 2.16.840.1.114027.80.9.1.9 id-MLDSA65-ECDSA-P384-SHA512 */
387+
ASN1ObjectIdentifier id_MLDSA65_ECDSA_P384_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.9");
388+
/** 2.16.840.1.114027.80.9.1.10 id-MLDSA65-ECDSA-brainpoolP256r1-SHA512 */
389+
ASN1ObjectIdentifier id_MLDSA65_ECDSA_brainpoolP256r1_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.10");
390+
/** 2.16.840.1.114027.80.9.1.11 id-MLDSA65-Ed25519-SHA512 */
391+
ASN1ObjectIdentifier id_MLDSA65_Ed25519_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.11");
392+
/** 2.16.840.1.114027.80.9.1.12 id-MLDSA87-ECDSA-P384-SHA512 */
393+
ASN1ObjectIdentifier id_MLDSA87_ECDSA_P384_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.12");
394+
/** 2.16.840.1.114027.80.9.1.13 id-MLDSA87-ECDSA-brainpoolP384r1-SHA512 */
395+
ASN1ObjectIdentifier id_MLDSA87_ECDSA_brainpoolP384r1_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.13");
396+
/** 2.16.840.1.114027.80.9.1.14 id-MLDSA87-Ed448-SHAKE256 */
397+
ASN1ObjectIdentifier id_MLDSA87_Ed448_SHAKE256 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.14");
398+
/** 2.16.840.1.114027.80.9.1.15 id-MLDSA87-RSA3072-PSS-SHA512 */
399+
ASN1ObjectIdentifier id_MLDSA87_RSA3072_PSS_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.15");
400+
/** 2.16.840.1.114027.80.9.1.16 id-MLDSA87-RSA4096-PSS-SHA512 */
401+
ASN1ObjectIdentifier id_MLDSA87_RSA4096_PSS_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.16");
402+
/** 2.16.840.1.114027.80.9.1.17 id-MLDSA87-ECDSA-P521-SHA512 */
403+
ASN1ObjectIdentifier id_MLDSA87_ECDSA_P521_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.17");
404+
368405
/*
369406
* Rainbow
370407
*/

core/src/main/java/org/bouncycastle/internal/asn1/misc/MiscObjectIdentifiers.java

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,17 +169,12 @@ public interface MiscObjectIdentifiers
169169
// Composite signature related OIDs. Based https://www.ietf.org/archive/id/draft-ounsworth-pq-composite-sigs-13.html
170170
// The current OIDs are EXPERIMENTAL and are going to change.
171171
ASN1ObjectIdentifier id_composite_signatures = new ASN1ObjectIdentifier("2.16.840.1.114027.80.8.1");
172-
ASN1ObjectIdentifier id_MLDSA44_RSA2048_PSS_SHA256 = id_composite_signatures.branch("21");
173-
ASN1ObjectIdentifier id_MLDSA44_RSA2048_PKCS15_SHA256 = id_composite_signatures.branch("22");
174-
ASN1ObjectIdentifier id_MLDSA44_Ed25519_SHA512 = id_composite_signatures.branch("23");
175-
ASN1ObjectIdentifier id_MLDSA44_ECDSA_P256_SHA256 = id_composite_signatures.branch("24");
176172
ASN1ObjectIdentifier id_MLDSA65_RSA3072_PSS_SHA256 = id_composite_signatures.branch("26");
177173
ASN1ObjectIdentifier id_MLDSA65_RSA3072_PKCS15_SHA256 = id_composite_signatures.branch("27");
178174
ASN1ObjectIdentifier id_MLDSA65_RSA4096_PSS_SHA384 = id_composite_signatures.branch("34");
179175
ASN1ObjectIdentifier id_MLDSA65_RSA4096_PKCS15_SHA384 = id_composite_signatures.branch("35");
180176
ASN1ObjectIdentifier id_MLDSA65_ECDSA_P384_SHA384 = id_composite_signatures.branch("28");
181177
ASN1ObjectIdentifier id_MLDSA65_ECDSA_brainpoolP256r1_SHA256 = id_composite_signatures.branch("29");
182-
ASN1ObjectIdentifier id_MLDSA65_Ed25519_SHA512 = id_composite_signatures.branch("30");
183178
ASN1ObjectIdentifier id_MLDSA87_ECDSA_P384_SHA384 = id_composite_signatures.branch("31");
184179
ASN1ObjectIdentifier id_MLDSA87_ECDSA_brainpoolP384r1_SHA384 = id_composite_signatures.branch("32");
185180
ASN1ObjectIdentifier id_MLDSA87_Ed448_SHA512 = id_composite_signatures.branch("33");
@@ -198,5 +193,44 @@ public interface MiscObjectIdentifiers
198193
ASN1ObjectIdentifier id_HashMLDSA87_ECDSA_P384_SHA512 = id_composite_signatures.branch("51");
199194
ASN1ObjectIdentifier id_HashMLDSA87_ECDSA_brainpoolP384r1_SHA512 = id_composite_signatures.branch("52");
200195
ASN1ObjectIdentifier id_HashMLDSA87_Ed448_SHA512 = id_composite_signatures.branch("53");
196+
197+
ASN1ObjectIdentifier id_MLDSA_COMPSIG = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1");
198+
/** 2.16.840.1.114027.80.9.1.0 id-MLDSA44-RSA2048-PSS-SHA256 */
199+
ASN1ObjectIdentifier id_MLDSA44_RSA2048_PSS_SHA256 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.0");
200+
/** 2.16.840.1.114027.80.9.1.1 id-MLDSA44-RSA2048-PKCS15-SHA256 */
201+
ASN1ObjectIdentifier id_MLDSA44_RSA2048_PKCS15_SHA256 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.1");
202+
/** 2.16.840.1.114027.80.9.1.2 id-MLDSA44-Ed25519-SHA512 */
203+
ASN1ObjectIdentifier id_MLDSA44_Ed25519_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.2");
204+
/** 2.16.840.1.114027.80.9.1.3 id-MLDSA44-ECDSA-P256-SHA256 */
205+
ASN1ObjectIdentifier id_MLDSA44_ECDSA_P256_SHA256 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.3");
206+
/** 2.16.840.1.114027.80.9.1.4 id-MLDSA65-RSA3072-PSS-SHA512 */
207+
ASN1ObjectIdentifier id_MLDSA65_RSA3072_PSS_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.4");
208+
/** 2.16.840.1.114027.80.9.1.5 id-MLDSA65-RSA3072-PKCS15-SHA512 */
209+
ASN1ObjectIdentifier id_MLDSA65_RSA3072_PKCS15_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.5");
210+
/** 2.16.840.1.114027.80.9.1.6 id-MLDSA65-RSA4096-PSS-SHA512 */
211+
ASN1ObjectIdentifier id_MLDSA65_RSA4096_PSS_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.6");
212+
/** 2.16.840.1.114027.80.9.1.7 id-MLDSA65-RSA4096-PKCS15-SHA512 */
213+
ASN1ObjectIdentifier id_MLDSA65_RSA4096_PKCS15_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.7");
214+
/** 2.16.840.1.114027.80.9.1.8 id-MLDSA65-ECDSA-P256-SHA512 */
215+
ASN1ObjectIdentifier id_MLDSA65_ECDSA_P256_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.8");
216+
/** 2.16.840.1.114027.80.9.1.9 id-MLDSA65-ECDSA-P384-SHA512 */
217+
ASN1ObjectIdentifier id_MLDSA65_ECDSA_P384_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.9");
218+
/** 2.16.840.1.114027.80.9.1.10 id-MLDSA65-ECDSA-brainpoolP256r1-SHA512 */
219+
ASN1ObjectIdentifier id_MLDSA65_ECDSA_brainpoolP256r1_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.10");
220+
/** 2.16.840.1.114027.80.9.1.11 id-MLDSA65-Ed25519-SHA512 */
221+
ASN1ObjectIdentifier id_MLDSA65_Ed25519_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.11");
222+
/** 2.16.840.1.114027.80.9.1.12 id-MLDSA87-ECDSA-P384-SHA512 */
223+
ASN1ObjectIdentifier id_MLDSA87_ECDSA_P384_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.12");
224+
/** 2.16.840.1.114027.80.9.1.13 id-MLDSA87-ECDSA-brainpoolP384r1-SHA512 */
225+
ASN1ObjectIdentifier id_MLDSA87_ECDSA_brainpoolP384r1_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.13");
226+
/** 2.16.840.1.114027.80.9.1.14 id-MLDSA87-Ed448-SHAKE256 */
227+
ASN1ObjectIdentifier id_MLDSA87_Ed448_SHAKE256 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.14");
228+
/** 2.16.840.1.114027.80.9.1.15 id-MLDSA87-RSA3072-PSS-SHA512 */
229+
ASN1ObjectIdentifier id_MLDSA87_RSA3072_PSS_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.15");
230+
/** 2.16.840.1.114027.80.9.1.16 id-MLDSA87-RSA4096-PSS-SHA512 */
231+
ASN1ObjectIdentifier id_MLDSA87_RSA4096_PSS_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.16");
232+
/** 2.16.840.1.114027.80.9.1.17 id-MLDSA87-ECDSA-P521-SHA512 */
233+
ASN1ObjectIdentifier id_MLDSA87_ECDSA_P521_SHA512 = new ASN1ObjectIdentifier("2.16.840.1.114027.80.9.1.17");
234+
201235
// COMPOSITE SIGNATURES END
202236
}

pkix/src/main/java/org/bouncycastle/cert/jcajce/JcaX509v3CertificateBuilder.java

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@
1010

1111
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
1212
import org.bouncycastle.asn1.x500.X500Name;
13+
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
1314
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
1415
import org.bouncycastle.asn1.x509.Time;
1516
import org.bouncycastle.cert.X509v3CertificateBuilder;
17+
import org.bouncycastle.asn1.misc.MiscObjectIdentifiers;
18+
import org.bouncycastle.jcajce.CompositePublicKey;
1619

1720
/**
1821
* JCA helper class to allow JCA objects to be used in the construction of a Version 3 certificate.
@@ -23,11 +26,11 @@ public class JcaX509v3CertificateBuilder
2326
/**
2427
* Initialise the builder using a PublicKey.
2528
*
26-
* @param issuer X500Name representing the issuer of this certificate.
27-
* @param serial the serial number for the certificate.
29+
* @param issuer X500Name representing the issuer of this certificate.
30+
* @param serial the serial number for the certificate.
2831
* @param notBefore date before which the certificate is not valid.
29-
* @param notAfter date after which the certificate is not valid.
30-
* @param subject X500Name representing the subject of this certificate.
32+
* @param notAfter date after which the certificate is not valid.
33+
* @param subject X500Name representing the subject of this certificate.
3134
* @param publicKey the public key to be associated with the certificate.
3235
*/
3336
public JcaX509v3CertificateBuilder(X500Name issuer, BigInteger serial, Date notBefore, Date notAfter, X500Name subject, SubjectPublicKeyInfo publicKey)
@@ -38,58 +41,58 @@ public JcaX509v3CertificateBuilder(X500Name issuer, BigInteger serial, Date notB
3841
/**
3942
* Initialise the builder using a PublicKey.
4043
*
41-
* @param issuer X500Name representing the issuer of this certificate.
42-
* @param serial the serial number for the certificate.
44+
* @param issuer X500Name representing the issuer of this certificate.
45+
* @param serial the serial number for the certificate.
4346
* @param notBefore date before which the certificate is not valid.
44-
* @param notAfter date after which the certificate is not valid.
45-
* @param subject X500Name representing the subject of this certificate.
47+
* @param notAfter date after which the certificate is not valid.
48+
* @param subject X500Name representing the subject of this certificate.
4649
* @param publicKey the public key to be associated with the certificate.
4750
*/
4851
public JcaX509v3CertificateBuilder(X500Name issuer, BigInteger serial, Date notBefore, Date notAfter, X500Name subject, PublicKey publicKey)
4952
{
50-
super(issuer, serial, notBefore, notAfter, subject, SubjectPublicKeyInfo.getInstance(publicKey.getEncoded()));
53+
super(issuer, serial, notBefore, notAfter, subject, getSubjectPublicKeyInfo(publicKey));
5154
}
5255

5356
/**
5457
* Initialise the builder using a PublicKey.
5558
*
56-
* @param issuer X500Name representing the issuer of this certificate.
57-
* @param serial the serial number for the certificate.
59+
* @param issuer X500Name representing the issuer of this certificate.
60+
* @param serial the serial number for the certificate.
5861
* @param notBefore Time before which the certificate is not valid.
59-
* @param notAfter Time after which the certificate is not valid.
60-
* @param subject X500Name representing the subject of this certificate.
62+
* @param notAfter Time after which the certificate is not valid.
63+
* @param subject X500Name representing the subject of this certificate.
6164
* @param publicKey the public key to be associated with the certificate.
6265
*/
6366
public JcaX509v3CertificateBuilder(X500Name issuer, BigInteger serial, Time notBefore, Time notAfter, X500Name subject, PublicKey publicKey)
6467
{
65-
super(issuer, serial, notBefore, notAfter, subject, SubjectPublicKeyInfo.getInstance(publicKey.getEncoded()));
68+
super(issuer, serial, notBefore, notAfter, subject, getSubjectPublicKeyInfo(publicKey));
6669
}
6770

6871
/**
6972
* Initialise the builder using X500Principal objects and a PublicKey.
7073
*
71-
* @param issuer principal representing the issuer of this certificate.
72-
* @param serial the serial number for the certificate.
74+
* @param issuer principal representing the issuer of this certificate.
75+
* @param serial the serial number for the certificate.
7376
* @param notBefore date before which the certificate is not valid.
74-
* @param notAfter date after which the certificate is not valid.
75-
* @param subject principal representing the subject of this certificate.
77+
* @param notAfter date after which the certificate is not valid.
78+
* @param subject principal representing the subject of this certificate.
7679
* @param publicKey the public key to be associated with the certificate.
7780
*/
7881
public JcaX509v3CertificateBuilder(X500Principal issuer, BigInteger serial, Date notBefore, Date notAfter, X500Principal subject, PublicKey publicKey)
7982
{
80-
super(X500Name.getInstance(issuer.getEncoded()), serial, notBefore, notAfter, X500Name.getInstance(subject.getEncoded()), SubjectPublicKeyInfo.getInstance(publicKey.getEncoded()));
83+
super(X500Name.getInstance(issuer.getEncoded()), serial, notBefore, notAfter, X500Name.getInstance(subject.getEncoded()), getSubjectPublicKeyInfo(publicKey));
8184
}
8285

8386
/**
8487
* Initialise the builder using the subject from the passed in issuerCert as the issuer, as well as
8588
* passing through and converting the other objects provided.
8689
*
8790
* @param issuerCert certificate who's subject is the issuer of the certificate we are building.
88-
* @param serial the serial number for the certificate.
89-
* @param notBefore date before which the certificate is not valid.
90-
* @param notAfter date after which the certificate is not valid.
91-
* @param subject principal representing the subject of this certificate.
92-
* @param publicKey the public key to be associated with the certificate.
91+
* @param serial the serial number for the certificate.
92+
* @param notBefore date before which the certificate is not valid.
93+
* @param notAfter date after which the certificate is not valid.
94+
* @param subject principal representing the subject of this certificate.
95+
* @param publicKey the public key to be associated with the certificate.
9396
*/
9497
public JcaX509v3CertificateBuilder(X509Certificate issuerCert, BigInteger serial, Date notBefore, Date notAfter, X500Principal subject, PublicKey publicKey)
9598
{
@@ -101,11 +104,11 @@ public JcaX509v3CertificateBuilder(X509Certificate issuerCert, BigInteger serial
101104
* passing through and converting the other objects provided.
102105
*
103106
* @param issuerCert certificate who's subject is the issuer of the certificate we are building.
104-
* @param serial the serial number for the certificate.
105-
* @param notBefore date before which the certificate is not valid.
106-
* @param notAfter date after which the certificate is not valid.
107-
* @param subject principal representing the subject of this certificate.
108-
* @param publicKey the public key to be associated with the certificate.
107+
* @param serial the serial number for the certificate.
108+
* @param notBefore date before which the certificate is not valid.
109+
* @param notAfter date after which the certificate is not valid.
110+
* @param subject principal representing the subject of this certificate.
111+
* @param publicKey the public key to be associated with the certificate.
109112
*/
110113
public JcaX509v3CertificateBuilder(X509Certificate issuerCert, BigInteger serial, Date notBefore, Date notAfter, X500Name subject, PublicKey publicKey)
111114
{
@@ -120,15 +123,15 @@ public JcaX509v3CertificateBuilder(X509Certificate issuerCert, BigInteger serial
120123
public JcaX509v3CertificateBuilder(X509Certificate template)
121124
throws CertificateEncodingException
122125
{
123-
super(new JcaX509CertificateHolder(template));
126+
super(new JcaX509CertificateHolder(template));
124127
}
125128

126129
/**
127130
* Add a given extension field for the standard extensions tag (tag 3)
128131
* copying the extension value from another certificate.
129132
*
130-
* @param oid the type of the extension to be copied.
131-
* @param critical true if the extension is to be marked critical, false otherwise.
133+
* @param oid the type of the extension to be copied.
134+
* @param critical true if the extension is to be marked critical, false otherwise.
132135
* @param certificate the source of the extension to be copied.
133136
* @return the builder instance.
134137
*/
@@ -142,4 +145,16 @@ public JcaX509v3CertificateBuilder copyAndAddExtension(
142145

143146
return this;
144147
}
148+
149+
private static SubjectPublicKeyInfo getSubjectPublicKeyInfo(PublicKey publicKey)
150+
{
151+
if (publicKey instanceof CompositePublicKey && ((CompositePublicKey)publicKey).getAlgorithmIdentifier().on(MiscObjectIdentifiers.id_MLDSA_COMPSIG))
152+
{
153+
return new SubjectPublicKeyInfo(new AlgorithmIdentifier(((CompositePublicKey)publicKey).getAlgorithmIdentifier()), publicKey.getEncoded());
154+
}
155+
else
156+
{
157+
return SubjectPublicKeyInfo.getInstance(publicKey.getEncoded());
158+
}
159+
}
145160
}

0 commit comments

Comments
 (0)