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 }