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