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