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