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