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