View Javadoc
1   /*
2    * Copyright 2024 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.pkitesting;
17  
18  import io.netty.util.internal.EmptyArrays;
19  import org.bouncycastle.asn1.ASN1Integer;
20  import org.bouncycastle.asn1.ASN1ObjectIdentifier;
21  import org.bouncycastle.asn1.DERBitString;
22  import org.bouncycastle.asn1.DERIA5String;
23  import org.bouncycastle.asn1.DERUTF8String;
24  import org.bouncycastle.asn1.x500.X500Name;
25  import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
26  import org.bouncycastle.asn1.x509.BasicConstraints;
27  import org.bouncycastle.asn1.x509.CRLDistPoint;
28  import org.bouncycastle.asn1.x509.DistributionPoint;
29  import org.bouncycastle.asn1.x509.DistributionPointName;
30  import org.bouncycastle.asn1.x509.Extension;
31  import org.bouncycastle.asn1.x509.ExtensionsGenerator;
32  import org.bouncycastle.asn1.x509.GeneralName;
33  import org.bouncycastle.asn1.x509.GeneralNames;
34  import org.bouncycastle.asn1.x509.KeyPurposeId;
35  import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
36  import org.bouncycastle.asn1.x509.Time;
37  import org.bouncycastle.asn1.x509.V3TBSCertificateGenerator;
38  import org.bouncycastle.jcajce.spec.EdDSAParameterSpec;
39  
40  import java.io.IOException;
41  import java.io.UncheckedIOException;
42  import java.math.BigInteger;
43  import java.net.InetAddress;
44  import java.net.URI;
45  import java.net.URISyntaxException;
46  import java.security.GeneralSecurityException;
47  import java.security.KeyPair;
48  import java.security.KeyPairGenerator;
49  import java.security.PrivateKey;
50  import java.security.PublicKey;
51  import java.security.SecureRandom;
52  import java.security.cert.CertificateFactory;
53  import java.security.cert.X509Certificate;
54  import java.security.interfaces.DSAPublicKey;
55  import java.security.interfaces.ECPublicKey;
56  import java.security.interfaces.RSAPublicKey;
57  import java.security.spec.AlgorithmParameterSpec;
58  import java.security.spec.ECGenParameterSpec;
59  import java.security.spec.RSAKeyGenParameterSpec;
60  import java.time.Instant;
61  import java.time.temporal.ChronoUnit;
62  import java.util.ArrayList;
63  import java.util.Date;
64  import java.util.List;
65  import java.util.OptionalInt;
66  import java.util.Set;
67  import java.util.TreeSet;
68  import javax.security.auth.x500.X500Principal;
69  
70  import static java.util.Objects.requireNonNull;
71  
72  /**
73   * The {@link CertificateBuilder} produce {@link X509Bundle} instances, where the keys use the specified
74   * algorithm, and the certificate have the specified data.
75   * <p>
76   * The builder can make self-signed bundles, or can make bundles that are signed by other bundles to build a verified
77   * certificate path.
78   * <p>
79   * The builder can also make certificate that are invalid in various ways, for testing purpose.
80   * The most typical application is to make a certificate that has already expired or is not yet valid.
81   * <p>
82   * See RFC 5280 for the details of X.509 certificate contents.
83   * <p>
84   * Here is an example where a leaf certificate is created and signed by a self-signed issuer certificate:
85   * <pre>{@code
86   * Instant now = Instant.now();
87   * CertificateBuilder template = new CertificateBuilder()
88   *             .notBefore(now.minus(1, DAYS))
89   *             .notAfter(now.plus(1, DAYS));
90   * X509Bundle issuer = template.copy()
91   *             .subject("CN=testca, OU=dept, O=your-org")
92   *             .setKeyUsage(true, KeyUsage.digitalSignature, KeyUsage.keyCertSign)
93   *             .setIsCertificateAuthority(true)
94   *             .buildSelfSigned();
95   * X509Bundle leaf = template.copy()
96   *             .subject("CN=leaf, OU=dept, O=your-org")
97   *             .setKeyUsage(true, KeyUsage.digitalSignature)
98   *             .addExtendedKeyUsage(ExtendedKeyUsage.PKIX_KP_SERVER_AUTH)
99   *             .addSanDnsName("san-1.leaf.dept.your-org.com")
100  *             .buildIssuedBy(issuer);
101  * }</pre>
102  */
103 public final class CertificateBuilder {
104 
105     static final String OID_X509_NAME_CONSTRAINTS = "2.5.29.30";
106     static final String OID_PKIX_KP = "1.3.6.1.5.5.7.3";
107     static final String OID_PKIX_KP_SERVER_AUTH = OID_PKIX_KP + ".1";
108     static final String OID_PKIX_KP_CLIENT_AUTH = OID_PKIX_KP + ".2";
109     static final String OID_PKIX_KP_CODE_SIGNING = OID_PKIX_KP + ".3";
110     static final String OID_PKIX_KP_EMAIL_PROTECTION = OID_PKIX_KP + ".4";
111     static final String OID_PKIX_KP_TIME_STAMPING = OID_PKIX_KP + ".8";
112     static final String OID_PKIX_KP_OCSP_SIGNING = OID_PKIX_KP + ".9";
113     static final String OID_KERBEROS_KEY_PURPOSE_CLIENT_AUTH = "1.3.6.1.5.2.3.4";
114     static final String OID_MICROSOFT_SMARTCARD_LOGIN = "1.3.6.1.4.1.311.20.2.2";
115     private static final GeneralName[] EMPTY_GENERAL_NAMES = new GeneralName[0];
116     private static final DistributionPoint[] EMPTY_DIST_POINTS = new DistributionPoint[0];
117     private static final AlgorithmParameterSpec UNSUPPORTED_SPEC = new AlgorithmParameterSpec() {
118     };
119 
120     SecureRandom random;
121     Algorithm algorithm = Algorithm.ecp256;
122     Instant notBefore = Instant.now().minus(1, ChronoUnit.DAYS);
123     Instant notAfter = Instant.now().plus(1, ChronoUnit.DAYS);
124     List<BuilderCallback> modifierCallbacks = new ArrayList<>();
125     List<GeneralName> subjectAlternativeNames = new ArrayList<>();
126     List<DistributionPoint> crlDistributionPoints = new ArrayList<>();
127     BigInteger serial;
128     X500Principal subject;
129     boolean isCertificateAuthority;
130     OptionalInt pathLengthConstraint = OptionalInt.empty();
131     PublicKey publicKey;
132     Set<String> extendedKeyUsage = new TreeSet<>();
133     Extension keyUsage;
134 
135     /**
136      * Create a new certificate builder with a default configuration.
137      * Unless specified otherwise, the builder will produce bundles that use the
138      * {@linkplain Algorithm#ecp256 NIST EC-P 256} key algorithm,
139      * and the certificates will be valid as of yesterday and expire tomorrow.
140      */
141     public CertificateBuilder() {
142     }
143 
144     /**
145      * Produce a copy of the current state in this certificate builder.
146      * @return A copy of this certificate builder.
147      */
148     public CertificateBuilder copy() {
149         CertificateBuilder copy = new CertificateBuilder();
150         copy.random = random;
151         copy.algorithm = algorithm;
152         copy.notBefore = notBefore;
153         copy.notAfter = notAfter;
154         copy.modifierCallbacks = new ArrayList<>(modifierCallbacks);
155         copy.subjectAlternativeNames = new ArrayList<>(subjectAlternativeNames);
156         copy.crlDistributionPoints = new ArrayList<>(crlDistributionPoints);
157         copy.serial = serial;
158         copy.subject = subject;
159         copy.isCertificateAuthority = isCertificateAuthority;
160         copy.pathLengthConstraint = pathLengthConstraint;
161         copy.publicKey = publicKey;
162         copy.keyUsage = keyUsage;
163         copy.extendedKeyUsage = new TreeSet<>(extendedKeyUsage);
164         return copy;
165     }
166 
167     /**
168      * Set the {@link SecureRandom} instance to use when generating keys.
169      * @param secureRandom The secure random instance to use.
170      * @return This certificate builder.
171      */
172     public CertificateBuilder secureRandom(SecureRandom secureRandom) {
173         random = requireNonNull(secureRandom);
174         return this;
175     }
176 
177     /**
178      * Set the not-before field of the certificate. The certificate will not be valid before this time.
179      * @param instant The not-before time.
180      * @return This certificate builder.
181      */
182     public CertificateBuilder notBefore(Instant instant) {
183         notBefore = requireNonNull(instant);
184         return this;
185     }
186 
187     /**
188      * Set the not-after field of the certificate. The certificate will not be valid after this time.
189      * @param instant The not-after time.
190      * @return This certificate builder.
191      */
192     public CertificateBuilder notAfter(Instant instant) {
193         notAfter = requireNonNull(instant);
194         return this;
195     }
196 
197     /**
198      * Set the specific serial number to use in the certificate.
199      * One will be generated randomly, if none is specified.
200      * @param serial The serial number to use, or {@code null}.
201      * @return This certificate builder.
202      */
203     public CertificateBuilder serial(BigInteger serial) {
204         this.serial = serial;
205         return this;
206     }
207 
208     /**
209      * Set the fully-qualified domain name (an X.500 name) as the subject of the certificate.
210      * @param fqdn The subject name to use.
211      * @return This certificate builder.
212      */
213     public CertificateBuilder subject(String fqdn) {
214         subject = new X500Principal(requireNonNull(fqdn));
215         return this;
216     }
217 
218     /**
219      * Set the subject name of the certificate to the given {@link X500Principal}.
220      * @param name The subject name to use.
221      * @return This certificate builder.
222      */
223     public CertificateBuilder subject(X500Principal name) {
224         subject = requireNonNull(name);
225         return this;
226     }
227 
228     /**
229      * Add an Other Name to the Subject Alternative Names, of the given OID type, and with the given encoded value.
230      * The type and value will be wrapped in a SEQUENCE.
231      * @param typeOid The OID type of the Other Name value.
232      * @param encodedValue The encoded Other Name value.
233      * @return This certificate builder.
234      */
235     public CertificateBuilder addSanOtherName(String typeOid, byte[] encodedValue) {
236         subjectAlternativeNames.add(GeneralNameUtils.otherName(typeOid, encodedValue));
237         return this;
238     }
239 
240     /**
241      * Add an RFC 822 name to the Subject Alternative Names.
242      * The RFC 822 standard is the obsolete specification for email, so these SANs are email addresses.
243      * @param name The email address to add to the SANs.
244      * @return This certificate builder.
245      */
246     public CertificateBuilder addSanRfc822Name(String name) {
247         subjectAlternativeNames.add(GeneralNameUtils.rfc822Name(name));
248         return this;
249     }
250 
251     /**
252      * Add a DNS name to the Subject Alternate Names.
253      * @param dns The DNS name to add.
254      * @return This certificate builder.
255      */
256     public CertificateBuilder addSanDnsName(String dns) {
257         if (dns.trim().isEmpty()) {
258             throw new IllegalArgumentException("Blank DNS SANs are forbidden by RFC 5280, Section 4.2.1.6.");
259         }
260         subjectAlternativeNames.add(GeneralNameUtils.dnsName(dns));
261         return this;
262     }
263 
264     // x400Address support intentionally omitted; not in common use.
265 
266     /**
267      * Add a Directory Name to the Subject Alternative Names.
268      * These are LDAP directory paths.
269      * @param dirName The directory name to add to the SANs.
270      * @return This certificate builder.
271      */
272     public CertificateBuilder addSanDirectoryName(String dirName) {
273         subjectAlternativeNames.add(GeneralNameUtils.directoryName(dirName));
274         return this;
275     }
276 
277     // ediPartyName support intentionally omitted; not in common use.
278 
279     /**
280      * Add a URI name to the Subject Alternative Names.
281      * @param uri The URI to add to the SANs.
282      * @return This certificate builder.
283      */
284     public CertificateBuilder addSanUriName(String uri) throws URISyntaxException {
285         subjectAlternativeNames.add(GeneralNameUtils.uriName(uri));
286         return this;
287     }
288 
289     /**
290      * Add a URI name to the Subject Alternative Names.
291      * @param uri The URI to add to the SANs.
292      * @return This certificate builder.
293      */
294     public CertificateBuilder addSanUriName(URI uri) {
295         subjectAlternativeNames.add(GeneralNameUtils.uriName(uri));
296         return this;
297     }
298 
299     /**
300      * Add an IP address to the Subject Alternative Names.
301      * IPv4 and IPv6 addresses are both supported and converted to their correct encoding.
302      * @param ipAddress The IP address to add to the SANs.
303      * @return This certificate builder.
304      */
305     public CertificateBuilder addSanIpAddress(String ipAddress) {
306         subjectAlternativeNames.add(GeneralNameUtils.ipAddress(ipAddress));
307         return this;
308     }
309 
310     /**
311      * Add an IP address to the Subject Alternative Names.
312      * IPv4 and IPv6 addresses are both supported and converted to their correct encoding.
313      * @param ipAddress The IP address to add to the SANs.
314      * @return This certificate builder.
315      */
316     public CertificateBuilder addSanIpAddress(InetAddress ipAddress) {
317         subjectAlternativeNames.add(GeneralNameUtils.ipAddress(ipAddress.getHostAddress()));
318         return this;
319     }
320 
321     /**
322      * Add a registeredID to the Subject Alternative Names.
323      * A registeredID is an OBJECT IDENTIFIER, or OID, in ASN.1 speak.
324      * @param oid The OID to add to the SANs.
325      * @return This certificate builder.
326      */
327     public CertificateBuilder addSanRegisteredId(String oid) {
328         subjectAlternativeNames.add(GeneralNameUtils.registeredId(oid));
329         return this;
330     }
331 
332     /**
333      * Add a URI distribution point for a certificate revocation list.
334      * <p>
335      * If you are testing certificate revocation using the {@link RevocationServer},
336      * you would obtain this URI from {@link RevocationServer#getCrlUri(X509Bundle)} with your intended issuer
337      * certificate bundle.
338      *
339      * @param uri The URI for the CRL file.
340      * @return This certificate builder.
341      */
342     public CertificateBuilder addCrlDistributionPoint(URI uri) {
343         GeneralName fullName = GeneralNameUtils.uriName(uri);
344         crlDistributionPoints.add(new DistributionPoint(
345                 new DistributionPointName(new GeneralNames(fullName)),
346                 null,
347                 null));
348         return this;
349     }
350 
351     /**
352      * Add a URI distribution point for a certificate revocation list.
353      * <p>
354      * If you are testing certificate revocation using the {@link RevocationServer},
355      * you would obtain this URI from {@link RevocationServer#getCrlUri(X509Bundle)} with your intended issuer
356      * certificate bundle.
357      *
358      * @param uri The URI for the CRL file.
359      * @param issuer The issuer that signs the CRL file.
360      * This MUST be {@code null} if the CRL issuer is also the issuer of the certificate being built.
361      * Otherwise, if this certificate and the CRL will be signed by different issuers, then this MUST be the subject
362      * name of the CRL signing certificate.
363      * @return This certificate builder.
364      */
365     public CertificateBuilder addCrlDistributionPoint(URI uri, X500Principal issuer) {
366         GeneralName fullName = GeneralNameUtils.uriName(uri);
367         GeneralName issuerName = GeneralNameUtils.directoryName(issuer);
368         crlDistributionPoints.add(new DistributionPoint(
369                 new DistributionPointName(new GeneralNames(fullName)),
370                 null,
371                 new GeneralNames(issuerName)));
372         return this;
373     }
374 
375     /**
376      * Set the certificate authority field.
377      * If this is set to {@code true}, then this builder can build self-signed certificates, and those certifiactes
378      * can be used to sign other certificates.
379      * @param isCA {@code true} if this builder should make CA certificates.
380      * @return This certificate builder.
381      */
382     public CertificateBuilder setIsCertificateAuthority(boolean isCA) {
383         isCertificateAuthority = isCA;
384         return this;
385     }
386 
387     /**
388      * Certificate Authority certificates may impose a limit to the length of the verified certificate path they permit.
389      * @param pathLengthConstraint The maximum verified path length, if any.
390      * @return This certificate builder.
391      */
392     public CertificateBuilder setPathLengthConstraint(OptionalInt pathLengthConstraint) {
393         this.pathLengthConstraint = requireNonNull(pathLengthConstraint, "pathLengthConstraint");
394         return this;
395     }
396 
397     /**
398      * Set the key algorithm to use. This also determines how certificates are signed.
399      * @param algorithm The algorithm to use when generating the private key.
400      * @return This certificate builder.
401      */
402     public CertificateBuilder algorithm(Algorithm algorithm) {
403         requireNonNull(algorithm, "algorithm");
404         if (algorithm.parameterSpec == UNSUPPORTED_SPEC) {
405             throw new UnsupportedOperationException("This algorithm is not supported: " + algorithm);
406         }
407         this.algorithm = algorithm;
408         return this;
409     }
410 
411     /**
412      * Make this certificate builder use the {@linkplain Algorithm#ecp256 NIST EC-P 256} elliptic curve key algorithm.
413      * This algorithm provides a good balance between security, compatibility, performance, and key & signature sizes.
414      * @return This certificate builder.
415      * @see Algorithm#ecp256
416      */
417     public CertificateBuilder ecp256() {
418         return algorithm(Algorithm.ecp256);
419     }
420 
421     /**
422      * Make this certificate builder use the {@linkplain Algorithm#rsa2048 2048-bit RSA} encryption and signing
423      * algorithm. This algorithm provides maximum compatibility, but keys are large and slow to generate.
424      * @return This certificate builder.
425      * @see Algorithm#rsa2048
426      */
427     public CertificateBuilder rsa2048() {
428         return algorithm(Algorithm.rsa2048);
429     }
430 
431     /**
432      * Instruct the certificate builder to not generate its own key pair, but to instead create a certificate that
433      * uses the given public key.
434      * <p>
435      * This method is useful if you want to use an existing key-pair, e.g. to emulate a certificate authority
436      * responding to a Certificate Signing Request (CSR).
437      * <p>
438      * If the given public key is {@code null} (the default) then a new key-pair will be generated instead.
439      *
440      * @param key The public key to wrap in a certificate.
441      * @return This certificate builder.
442      */
443     public CertificateBuilder publicKey(PublicKey key) {
444         publicKey = key;
445         return this;
446     }
447 
448     private CertificateBuilder addExtension(String identifierOid, boolean critical, byte[] value) {
449         requireNonNull(identifierOid, "identifierOid");
450         requireNonNull(value, "value");
451         modifierCallbacks.add(builder -> {
452             builder.addExtension(new Extension(
453                     new ASN1ObjectIdentifier(identifierOid),
454                     critical,
455                     value));
456         });
457         return this;
458     }
459 
460     /**
461      * Add a custom extension to the certificate, with the given OID, criticality flag, and DER-encoded contents.
462      * @param identifierOID The OID identifying the extension.
463      * @param critical {@code true} if the extension is critical, otherwise {@code false}.
464      * Certificate systems MUST reject certificates with critical extensions they don't recognize.
465      * @param contents The DER-encoded extension contents.
466      * @return This certificate builder.
467      */
468     public CertificateBuilder addExtensionOctetString(String identifierOID, boolean critical, byte[] contents) {
469         requireNonNull(identifierOID, "identifierOID");
470         requireNonNull(contents, "contents");
471         modifierCallbacks.add(builder -> {
472             builder.addExtension(new Extension(
473                     new ASN1ObjectIdentifier(identifierOID),
474                     critical,
475                     contents));
476         });
477         return this;
478     }
479 
480     /**
481      * Add a custom DER-encoded ASN.1 UTF-8 string extension to the certificate, with the given OID, criticality,
482      * and string value.
483      * The string will be converted to its proper binary encoding by this method.
484      * @param identifierOID The OID identifying the extension.
485      * @param critical {@code true} if the extension is critical, otherwise {@code false}.
486      * Certificate systems MUST reject certificates with critical extensions they don't recognize.
487      * @param value The string value.
488      * @return This certificate builder.
489      */
490     public CertificateBuilder addExtensionUtf8String(String identifierOID, boolean critical, String value) {
491         try {
492             return addExtension(identifierOID, critical, new DERUTF8String(value).getEncoded("DER"));
493         } catch (IOException e) {
494             throw new UncheckedIOException(e);
495         }
496     }
497 
498     /**
499      * Add a custom DER-encoded ASN.1 IA5String (an ASCII string) extension to the certificate, with the given OID,
500      * criticality, and string value.
501      * The string will be converted to its proper binary encoding by this method.
502      * @param identifierOID The OID identifying the extension.
503      * @param critical {@code true} if the extension is critical, otherwise {@code false}.
504      * Certificate systems MUST reject certificates with critical extensions they don't recognize.
505      * @param value The string value.
506      * @return This certificate builder.
507      */
508     public CertificateBuilder addExtensionAsciiString(String identifierOID, boolean critical, String value) {
509         try {
510             return addExtension(identifierOID, critical, new DERIA5String(value).getEncoded("DER"));
511         } catch (IOException e) {
512             throw new UncheckedIOException(e);
513         }
514     }
515 
516     /**
517      * The key usage specify the intended usages for which the certificate has been issued.
518      * Some are overlapping, some are deprecated, and some are implied by usage.
519      * <p>
520      * For Certificate Authority usage, the important ones are {@link KeyUsage#keyCertSign}
521      * and {@link KeyUsage#cRLSign}.
522      * <p>
523      * Any certificate that has {@link KeyUsage#keyCertSign} must also have {@link #setIsCertificateAuthority(boolean)}
524      * set to {@code true}.
525      *
526      * @param critical {@code true} if certificate recipients are required to understand all the set bits,
527      * otherwise {@code false}.
528      * @param keyUsages The key usages to set.
529      * @return This certificate builder.
530      */
531     public CertificateBuilder setKeyUsage(boolean critical, KeyUsage... keyUsages) {
532         int maxBit = 0;
533         for (KeyUsage usage : keyUsages) {
534             maxBit = Math.max(usage.bitId, maxBit);
535         }
536         boolean[] bits = new boolean[maxBit + 1];
537         for (KeyUsage usage : keyUsages) {
538             bits[usage.bitId] = true;
539         }
540         int padding = 8 - bits.length % 8;
541         int lenBytes = bits.length / 8 + 1;
542         if (padding == 8) {
543             padding = 0;
544             lenBytes--;
545         }
546         byte[] bytes = new byte[lenBytes];
547         for (int i = 0; i < bits.length; i++) {
548             if (bits[i]) {
549                 int byteIndex = i / 8;
550                 int bitIndex = i % 8;
551                 bytes[byteIndex] |= (byte) (0x80 >>> bitIndex);
552             }
553         }
554 
555         try {
556             keyUsage = new Extension(
557                     Extension.keyUsage,
558                     critical,
559                     new DERBitString(bytes, padding).getEncoded("DER"));
560         } catch (IOException e) {
561             throw new UncheckedIOException(e);
562         }
563         return this;
564     }
565 
566     /**
567      * Add the given OID to the list of extended key usages.
568      * @param oid The OID to add.
569      * @return This certificate builder.
570      * @see ExtendedKeyUsage
571      * @see #addExtendedKeyUsage(ExtendedKeyUsage)
572      */
573     public CertificateBuilder addExtendedKeyUsage(String oid) {
574         extendedKeyUsage.add(oid);
575         return this;
576     }
577 
578     /**
579      * Add the given {@link ExtendedKeyUsage} to the list of extended key usages.
580      * @param keyUsage The extended key usage to add.
581      * @return This certificate builder.
582      */
583     public CertificateBuilder addExtendedKeyUsage(ExtendedKeyUsage keyUsage) {
584         extendedKeyUsage.add(keyUsage.getOid());
585         return this;
586     }
587 
588     /**
589      * Add server-authentication to the list of extended key usages.
590      * @return This certificate builder.
591      */
592     public CertificateBuilder addExtendedKeyUsageServerAuth() {
593         return addExtendedKeyUsage(ExtendedKeyUsage.PKIX_KP_SERVER_AUTH);
594     }
595 
596     /**
597      * Add client-authentication to the list of extended key usages.
598      * @return This certificate builder.
599      */
600     public CertificateBuilder addExtendedKeyUsageClientAuth() {
601         return addExtendedKeyUsage(ExtendedKeyUsage.PKIX_KP_CLIENT_AUTH);
602     }
603 
604     /**
605      * Add code signing to the list of extended key usages.
606      * @return This certificate builder.
607      */
608     public CertificateBuilder addExtendedKeyUsageCodeSigning() {
609         return addExtendedKeyUsage(ExtendedKeyUsage.PKIX_KP_CODE_SIGNING);
610     }
611 
612     /**
613      * Add email protection to the list of extended key usages.
614      * @return This certificate builder.
615      */
616     public CertificateBuilder addExtendedKeyUsageEmailProtection() {
617         return addExtendedKeyUsage(ExtendedKeyUsage.PKIX_KP_EMAIL_PROTECTION);
618     }
619 
620     /**
621      * Add time-stamping to the list of extended key usages.
622      * @return This certificate builder.
623      */
624     public CertificateBuilder addExtendedKeyUsageTimeStamping() {
625         return addExtendedKeyUsage(ExtendedKeyUsage.PKIX_KP_TIME_STAMPING);
626     }
627 
628     /**
629      * Add OCSP signing to the list of extended key usages.
630      * @return This certificate builder.
631      */
632     public CertificateBuilder addExtendedKeyUsageOcspSigning() {
633         return addExtendedKeyUsage(ExtendedKeyUsage.PKIX_KP_OCSP_SIGNING);
634     }
635 
636     /**
637      * Add Kerberos client authentication to the list of extended key usages.
638      * @return This certificate builder.
639      */
640     public CertificateBuilder addExtendedKeyUsageKerberosClientAuth() {
641         return addExtendedKeyUsage(ExtendedKeyUsage.KERBEROS_KEY_PURPOSE_CLIENT_AUTH);
642     }
643 
644     /**
645      * Add Microsoft smartcard login to the list of extended key usages.
646      * @return This certificate builder.
647      */
648     public CertificateBuilder addExtendedKeyUsageMicrosoftSmartcardLogin() {
649         return addExtendedKeyUsage(ExtendedKeyUsage.MICROSOFT_SMARTCARD_LOGIN);
650     }
651 
652     /**
653      * Build a {@link X509Bundle} with a self-signed certificate.
654      * @return The newly created bundle.
655      * @throws Exception If something went wrong in the process.
656      */
657     public X509Bundle buildSelfSigned() throws Exception {
658         if (publicKey != null) {
659             throw new IllegalStateException("Cannot create a self-signed certificate with a public key from a CSR.");
660         }
661         KeyPair keyPair = generateKeyPair();
662 
663         V3TBSCertificateGenerator generator = createCertBuilder(subject, subject, keyPair, algorithm.signatureType);
664 
665         addExtensions(generator);
666 
667         Signed signed = new Signed(tbsCertToBytes(generator), algorithm.signatureType, keyPair.getPrivate());
668         CertificateFactory factory = CertificateFactory.getInstance("X.509");
669         X509Certificate cert = (X509Certificate) factory.generateCertificate(signed.toInputStream());
670         return X509Bundle.fromRootCertificateAuthority(cert, keyPair);
671     }
672 
673     /**
674      * Build a {@link X509Bundle} with a certificate signed by the given issuer bundle.
675      * The signing algorithm used will be derived from the issuers public key.
676      * @return The newly created bundle.
677      * @throws Exception If something went wrong in the process.
678      */
679     public X509Bundle buildIssuedBy(X509Bundle issuerBundle) throws Exception {
680         String issuerSignAlgorithm = preferredSignatureAlgorithm(issuerBundle.getCertificate().getPublicKey());
681         return buildIssuedBy(issuerBundle, issuerSignAlgorithm);
682     }
683 
684     /**
685      * Build a {@link X509Bundle} with a certificate signed by the given issuer bundle, using the specified
686      * signing algorithm.
687      * @return The newly created bundle.
688      * @throws Exception If something went wrong in the process.
689      */
690     public X509Bundle buildIssuedBy(X509Bundle issuerBundle, String signAlg) throws Exception {
691         final KeyPair keyPair;
692         if (publicKey == null) {
693             keyPair = generateKeyPair();
694         } else {
695             keyPair = new KeyPair(publicKey, null);
696         }
697 
698         X500Principal issuerPrincipal = issuerBundle.getCertificate().getSubjectX500Principal();
699         V3TBSCertificateGenerator generator = createCertBuilder(issuerPrincipal, subject, keyPair, signAlg);
700 
701         addExtensions(generator);
702 
703         PrivateKey issuerPrivateKey = issuerBundle.getKeyPair().getPrivate();
704         if (issuerPrivateKey == null) {
705             throw new IllegalArgumentException(
706                     "Cannot sign certificate with issuer bundle that does not have a private key.");
707         }
708         Signed signed = new Signed(tbsCertToBytes(generator), signAlg, issuerPrivateKey);
709         CertificateFactory factory = CertificateFactory.getInstance("X.509");
710         X509Certificate cert = (X509Certificate) factory.generateCertificate(signed.toInputStream());
711         X509Certificate[] issuerPath = issuerBundle.getCertificatePath();
712         X509Certificate[] path = new X509Certificate[issuerPath.length + 1];
713         path[0] = cert;
714         System.arraycopy(issuerPath, 0, path, 1, issuerPath.length);
715         return X509Bundle.fromCertificatePath(path, issuerBundle.getRootCertificate(), keyPair);
716     }
717 
718     private static String preferredSignatureAlgorithm(PublicKey key) {
719         if (key instanceof RSAPublicKey) {
720             RSAPublicKey rsa = (RSAPublicKey) key;
721             if (rsa.getModulus().bitLength() < 4096) {
722                 return "SHA256withRSA";
723             }
724             return "SHA384withRSA";
725         }
726         if (key instanceof ECPublicKey) {
727             ECPublicKey ec = (ECPublicKey) key;
728             int size = ec.getW().getAffineX().bitLength();
729             // Note: the coords are not guaranteed to use up all available bits, hence less-than-or-equal checks.
730             if (size <= 256) {
731                 return "SHA256withECDSA";
732             }
733             if (size <= 384) {
734                 return "SHA384withECDSA";
735             }
736             return "SHA512withECDSA";
737         }
738         if (key instanceof DSAPublicKey) {
739             throw new IllegalArgumentException("DSA keys are not supported because they are obsolete.");
740         }
741         String keyAlgorithm = key.getAlgorithm();
742         if ("Ed25519".equals(keyAlgorithm) || "1.3.101.112".equals(keyAlgorithm)) {
743             return "Ed25519";
744         }
745         if ("Ed448".equals(keyAlgorithm) || "1.3.101.113".equals(keyAlgorithm)) {
746             return "Ed448";
747         }
748         if ("EdDSA".equals(keyAlgorithm)) {
749             byte[] encoded = key.getEncoded();
750             if (encoded.length <= 44) {
751                 return "Ed25519";
752             }
753             if (encoded.length <= 69) {
754                 return "Ed448";
755             }
756         }
757         throw new IllegalArgumentException("Don't know what signature algorithm is best for " + key);
758     }
759 
760     private KeyPair generateKeyPair() throws GeneralSecurityException {
761         return algorithm.generateKeyPair(getSecureRandom());
762     }
763 
764     private V3TBSCertificateGenerator createCertBuilder(
765             X500Principal issuer, X500Principal subject, KeyPair keyPair, String signAlg) {
766         BigInteger serial = this.serial != null ? this.serial : new BigInteger(159, getSecureRandom());
767         PublicKey pubKey = keyPair.getPublic();
768 
769         V3TBSCertificateGenerator generator = new V3TBSCertificateGenerator();
770         generator.setIssuer(X500Name.getInstance(issuer.getEncoded()));
771         if (subject != null) {
772             generator.setSubject(X500Name.getInstance(subject.getEncoded()));
773         }
774         generator.setSerialNumber(new ASN1Integer(serial));
775         generator.setSignature(new AlgorithmIdentifier(new ASN1ObjectIdentifier(
776                 Algorithms.oidForAlgorithmName(signAlg))));
777         generator.setStartDate(new Time(Date.from(notBefore)));
778         generator.setEndDate(new Time(Date.from(notAfter)));
779         generator.setSubjectPublicKeyInfo(SubjectPublicKeyInfo.getInstance(pubKey.getEncoded()));
780         return generator;
781     }
782 
783     private static byte[] tbsCertToBytes(V3TBSCertificateGenerator generator) {
784         try {
785             return generator.generateTBSCertificate().getEncoded("DER");
786         } catch (IOException e) {
787             throw new UncheckedIOException(e);
788         }
789     }
790 
791     private SecureRandom getSecureRandom() {
792         SecureRandom rng = random;
793         if (rng == null) {
794             rng = SecureRandomHolder.RANDOM;
795         }
796         return rng;
797     }
798 
799     private void addExtensions(V3TBSCertificateGenerator tbsCert) throws Exception {
800         ExtensionsGenerator generator = new ExtensionsGenerator();
801         if (isCertificateAuthority) {
802             final BasicConstraints basicConstraints;
803             if (pathLengthConstraint.isPresent()) {
804                 basicConstraints = new BasicConstraints(pathLengthConstraint.getAsInt());
805             } else {
806                 basicConstraints = new BasicConstraints(true);
807             }
808             final byte[] basicConstraintsBytes = basicConstraints.getEncoded("DER");
809             generator.addExtension(new Extension(Extension.basicConstraints, true, basicConstraintsBytes));
810         }
811         if (keyUsage != null) {
812             generator.addExtension(keyUsage);
813         }
814 
815         if (!extendedKeyUsage.isEmpty()) {
816             KeyPurposeId[] usages = new KeyPurposeId[extendedKeyUsage.size()];
817             String[] usagesStrings = extendedKeyUsage.toArray(EmptyArrays.EMPTY_STRINGS);
818             for (int i = 0; i < usagesStrings.length; i++) {
819                 usages[i] = KeyPurposeId.getInstance(new ASN1ObjectIdentifier(usagesStrings[i]));
820             }
821             byte[] der = new org.bouncycastle.asn1.x509.ExtendedKeyUsage(usages).getEncoded("DER");
822             generator.addExtension(new Extension(Extension.extendedKeyUsage, false, der));
823         }
824 
825         if (!subjectAlternativeNames.isEmpty()) {
826             // SAN is critical extension if subject is empty sequence:
827             boolean critical = subject.getName().isEmpty();
828             byte[] result;
829             GeneralNames generalNames = new GeneralNames(subjectAlternativeNames.toArray(EMPTY_GENERAL_NAMES));
830             try {
831                 result = generalNames.getEncoded("DER");
832             } catch (IOException e) {
833                 throw new UncheckedIOException(e);
834             }
835             generator.addExtension(new Extension(Extension.subjectAlternativeName, critical, result));
836         }
837 
838         if (!crlDistributionPoints.isEmpty()) {
839             generator.addExtension(Extension.create(
840                     Extension.cRLDistributionPoints,
841                     false,
842                     new CRLDistPoint(crlDistributionPoints.toArray(EMPTY_DIST_POINTS))));
843         }
844 
845         for (BuilderCallback callback : modifierCallbacks) {
846             callback.modify(generator);
847         }
848 
849         if (!generator.isEmpty()) {
850             tbsCert.setExtensions(generator.generate());
851         }
852     }
853 
854     /**
855      * The {@link Algorithm} enum encapsulates both the key type, key generation parameters, and the signature
856      * algorithm to use.
857      */
858     public enum Algorithm {
859         /**
860          * The NIST P-256 elliptic curve algorithm, offer fast key generation, signing, and verification,
861          * with small keys and signatures, at 128-bits of security strength.
862          * <p>
863          * This algorithm is older than the Edwards curves, and are more widely supported.
864          */
865         ecp256("EC", new ECGenParameterSpec("secp256r1"), "SHA256withECDSA"),
866         /**
867          * The NIST P-384 elliptic curve algorithm, offer fast key generation, signing, and verification,
868          * with small keys and signatures, at 192-bits of security strength.
869          * <p>
870          * This algorithm is older than the Edwards curves, and are more widely supported.
871          */
872         ecp384("EC", new ECGenParameterSpec("secp384r1"), "SHA384withECDSA"),
873         /**
874          * The 2048-bit RSA algorithm offer roughly 112-bits of security strength, at the cost of large keys
875          * and slightly expensive key generation.
876          * <p>
877          * This algorithm enjoy the widest support and compatibility, though.
878          */
879         rsa2048("RSA", new RSAKeyGenParameterSpec(2048, RSAKeyGenParameterSpec.F4), "SHA256withRSA"),
880         /**
881          * The 3072-bit RSA algorithm offer roughly 128-bits of security strength, at the cost of large keys
882          * and fairly expensive key generation.
883          * <p>
884          * RSA enjoy pretty wide compatibility, though not all systems support keys this large.
885          */
886         rsa3072("RSA", new RSAKeyGenParameterSpec(3072, RSAKeyGenParameterSpec.F4), "SHA256withRSA"),
887         /**
888          * The 4096-bit RSA algorithm offer roughly greater than 128-bits of security strength,
889          * at the cost of large keys and very expensive key generation.
890          * <p>
891          * RSA enjoy pretty wide compatibility, though not all systems support keys this large.
892          */
893         rsa4096("RSA", new RSAKeyGenParameterSpec(4096, RSAKeyGenParameterSpec.F4), "SHA384withRSA"),
894         /**
895          * The 8192-bit RSA algorithm offer roughly greater than 192-bits of security strength,
896          * at the cost of very large keys and extremely expensive key generation.
897          * <p>
898          * RSA enjoy pretty wide compatibility, though not all systems support keys this large.
899          */
900         rsa8192("RSA", new RSAKeyGenParameterSpec(8192, RSAKeyGenParameterSpec.F4), "SHA384withRSA"),
901         /**
902          * The Ed25519 algorithm offer fast key generation, signing, and verification,
903          * with very small keys and signatures, at 128-bits of security strength.
904          * <p>
905          * This algorithm was added in Java 15, and may not be supported everywhere.
906          */
907         ed25519("Ed25519", namedParameterSpec("Ed25519"), "Ed25519"),
908         /**
909          * The Ed448 algorithm offer fast key generation, signing, and verification,
910          * with small keys and signatures, at 224-bits of security strength.
911          * <p>
912          * This algorithm was added in Java 15, and may not be supported everywhere.
913          */
914         ed448("Ed448", namedParameterSpec("Ed448"), "Ed448"),
915         /**
916          * The ML-DSA-44 algorithm is the NIST FIPS 204 version of the post-quantum Dilithium algorithm.
917          * It has 128-bits of classical security strength, and is claimed to meet NIST Level 2
918          * quantum security strength (equivalent to finding a SHA-256 collision).
919          * <p>
920          * This algorithm was added in Java 24, and may not be supported everywhere.
921          */
922         mlDsa44("ML-DSA", namedParameterSpec("ML-DSA-44"), "ML-DSA-44"),
923         /**
924          * The ML-DSA-65 algorithm is the NIST FIPS 204 version of the post-quantum Dilithium algorithm.
925          * It has 192-bits of classical security strength, and is claimed to meet NIST Level 3
926          * quantum security strength (equivalent to finding the key for an AES-192 block).
927          * <p>
928          * This algorithm was added in Java 24, and may not be supported everywhere.
929          */
930         mlDsa65("ML-DSA", namedParameterSpec("ML-DSA-65"), "ML-DSA-65"),
931         /**
932          * The ML-DSA-87 algorithm is the NIST FIPS 204 version of the post-quantum Dilithium algorithm.
933          * It has 256-bits of classical security strength, and is claimed to meet NIST Level 5
934          * quantum security strength (equivalent to finding the key for an AES-256 block).
935          * <p>
936          * This algorithm was added in Java 24, and may not be supported everywhere.
937          */
938         mlDsa87("ML-DSA", namedParameterSpec("ML-DSA-87"), "ML-DSA-87");
939 
940         final String keyType;
941         final AlgorithmParameterSpec parameterSpec;
942         final String signatureType;
943 
944         Algorithm(String keyType, AlgorithmParameterSpec parameterSpec, String signatureType) {
945             this.keyType = keyType;
946             this.parameterSpec = parameterSpec;
947             this.signatureType = signatureType;
948         }
949 
950         private static AlgorithmParameterSpec namedParameterSpec(String name) {
951             try {
952                 Class<?> cls = Class.forName("java.security.spec.NamedParameterSpec");
953                 return (AlgorithmParameterSpec) cls.getConstructor(String.class).newInstance(name);
954             } catch (Exception e) {
955                 if ("Ed25519".equals(name)) {
956                     return new EdDSAParameterSpec(EdDSAParameterSpec.Ed25519);
957                 }
958                 if ("Ed448".equals(name)) {
959                     return new EdDSAParameterSpec(EdDSAParameterSpec.Ed448);
960                 }
961                 return UNSUPPORTED_SPEC;
962             }
963         }
964 
965         /**
966          * Generate a new {@link KeyPair} using this algorithm, and the given {@link SecureRandom} generator.
967          * @param secureRandom The {@link SecureRandom} generator to use, not {@code null}.
968          * @return The generated {@link KeyPair}.
969          * @throws GeneralSecurityException if the key pair cannot be generated using this algorithm for some reason.
970          * @throws UnsupportedOperationException if this algorithm is not support in the current JVM.
971          */
972         public KeyPair generateKeyPair(SecureRandom secureRandom)
973                 throws GeneralSecurityException {
974             requireNonNull(secureRandom, "secureRandom");
975 
976             if (parameterSpec == UNSUPPORTED_SPEC) {
977                 throw new UnsupportedOperationException("This algorithm is not supported: " + this);
978             }
979             if (this == mlDsa44 || this == mlDsa65 || this == mlDsa87) {
980                 return genMlDsaKeyPair(secureRandom);
981             }
982             return genKeyPair(secureRandom);
983         }
984 
985         private KeyPair genMlDsaKeyPair(SecureRandom secureRandom) throws GeneralSecurityException {
986             final byte[] seed = new byte[32];
987             KeyPair keyPair = genKeyPair(new SecureRandom() {
988                 @Override
989                 public void nextBytes(byte[] bytes) {
990                     assert bytes.length == 32;
991                     secureRandom.nextBytes(bytes);
992                     System.arraycopy(bytes, 0, seed, 0, seed.length);
993                 }
994             });
995             return new KeyPair(keyPair.getPublic(), new MLDSASeedPrivateKey(keyPair.getPrivate(), this, seed));
996         }
997 
998         private KeyPair genKeyPair(SecureRandom secureRandom) throws GeneralSecurityException {
999             KeyPairGenerator keyGen = Algorithms.keyPairGenerator(keyType, parameterSpec, secureRandom);
1000             return keyGen.generateKeyPair();
1001         }
1002 
1003         /**
1004          * Tell whether this algorithm is supported in the current JVM.
1005          * @return {@code true} if this algorithm is supported.
1006          */
1007         public boolean isSupported() {
1008             return parameterSpec != UNSUPPORTED_SPEC;
1009         }
1010     }
1011 
1012     /**
1013      * The key usage field specify what the certificate and key is allowed to be used for.
1014      * <p>
1015      * These key usages are specified by the X.509 standard, and some of them are deprecated.
1016      * <p>
1017      * See the {@link ExtendedKeyUsage} for other commonly used key usage extensions.
1018      * <p>
1019      * See ITU-T X.509 (10/2019) section 9.2.2.3 for the precise meaning of these usages.
1020      */
1021     public enum KeyUsage {
1022         /**
1023          * For verifying digital signatures, for entity authentication,
1024          * for entity authentication, or for integrity verification.
1025          */
1026         digitalSignature(0),
1027         /**
1028          * This key usage is deprecated by X.509, and commitment may instead be derived from the actual use of the keys.
1029          * <p>
1030          * For verifying digital signatures that imply the signer has "committed" to the
1031          * content being signed. This does not imply any specific policy or review on part of the signer, however.
1032          */
1033         contentCommitment(1),
1034         /**
1035          * For enciphering keys or other security information.
1036          */
1037         keyEncipherment(2),
1038         /**
1039          * For enciphering user data, but not keys or security information.
1040          */
1041         dataEncipherment(3),
1042         /**
1043          * For use in public key agreement.
1044          */
1045         keyAgreement(4),
1046         /**
1047          * For verifying the Certificate Authority's signature on a public-key certificate.
1048          * <p>
1049          * This implies {@link #digitalSignature} and {@link #contentCommitment}, so they do not need to be specified
1050          * separately.
1051          */
1052         keyCertSign(5),
1053         /**
1054          * For verifying the Certificate Authority's signature on a Certificate Revocation List.
1055          * <p>
1056          * This implies {@link #digitalSignature} and {@link #contentCommitment}, so they do not need to be specified
1057          * separately.
1058          */
1059         cRLSign(6),
1060         /**
1061          * For use with {@link #keyAgreement} to limit the key to enciphering only.
1062          * <p>
1063          * The meaning of this without the {@link #keyAgreement} bit set is unspecified.
1064          */
1065         encipherOnly(7),
1066         /**
1067          * For use with {@link #keyAgreement} to limit the key to deciphering only.
1068          * <p>
1069          * The meaning of this without the {@link #keyAgreement} bit set is unspecified.
1070          */
1071         decipherOnly(8);
1072 
1073         private final int bitId;
1074 
1075         KeyUsage(int bitId) {
1076             this.bitId = bitId;
1077         }
1078     }
1079 
1080     /**
1081      * The extended key usage field specify what the certificate and key is allowed to be used for.
1082      * <p>
1083      * A certificate can have many key usages. For instance, some certificates support both client and server usage
1084      * for TLS connections.
1085      * <p>
1086      * The key usage must be checked by the opposing peer receiving the certificate, and reject certificates that do
1087      * not permit the given usage.
1088      * <p>
1089      * For instance, if a TLS client connects to a server that presents a certificate without the
1090      * {@linkplain #PKIX_KP_SERVER_AUTH server-authentication} usage, then the client must reject the server
1091      * certificate as invalid.
1092      */
1093     public enum ExtendedKeyUsage {
1094         /**
1095          * The certificate can be used on the server-side of a TLS connection.
1096          */
1097         PKIX_KP_SERVER_AUTH(OID_PKIX_KP_SERVER_AUTH),
1098         /**
1099          * The certificate can be used on the client-side of a TLS connection.
1100          */
1101         PKIX_KP_CLIENT_AUTH(OID_PKIX_KP_CLIENT_AUTH),
1102         /**
1103          * The certificate can be used for code signing.
1104          */
1105         PKIX_KP_CODE_SIGNING(OID_PKIX_KP_CODE_SIGNING),
1106         /**
1107          * The certificate can be used for protecting email.
1108          */
1109         PKIX_KP_EMAIL_PROTECTION(OID_PKIX_KP_EMAIL_PROTECTION),
1110         /**
1111          * The certificate can be used for time-stamping.
1112          */
1113         PKIX_KP_TIME_STAMPING(OID_PKIX_KP_TIME_STAMPING),
1114         /**
1115          * The certificate can be used to sign OCSP replies.
1116          */
1117         PKIX_KP_OCSP_SIGNING(OID_PKIX_KP_OCSP_SIGNING),
1118         /**
1119          * The certificate can be used for Kerberos client authentication.
1120          */
1121         KERBEROS_KEY_PURPOSE_CLIENT_AUTH(OID_KERBEROS_KEY_PURPOSE_CLIENT_AUTH),
1122         /**
1123          * The certificate can be used for Microsoft smartcard logins.
1124          */
1125         MICROSOFT_SMARTCARD_LOGIN(OID_MICROSOFT_SMARTCARD_LOGIN);
1126 
1127         private final String oid;
1128 
1129         ExtendedKeyUsage(String oid) {
1130             this.oid = oid;
1131         }
1132 
1133         public String getOid() {
1134             return oid;
1135         }
1136     }
1137 
1138     @FunctionalInterface
1139     private interface BuilderCallback {
1140         void modify(ExtensionsGenerator builder) throws Exception;
1141     }
1142 
1143     private static final class SecureRandomHolder {
1144         private static final SecureRandom RANDOM = new SecureRandom();
1145     }
1146 }