diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java index f8ab0126..66f61f4d 100644 --- a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java +++ b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java @@ -66,7 +66,7 @@ public class CSRBuilder { *

* IDN domain names are ACE encoded automatically. *

- * Note that ACME servers may not accept wildcard domains! + * For wildcard certificates, the domain name must be prefixed with {@code "*."}. * * @param domain * Domain name to add diff --git a/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CSRBuilderTest.java b/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CSRBuilderTest.java index 2771ad87..9ef68a44 100644 --- a/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CSRBuilderTest.java +++ b/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CSRBuilderTest.java @@ -72,6 +72,7 @@ public class CSRBuilderTest { builder.addDomain("fg.hi"); builder.addDomains("jklm.no", "pqr.st"); builder.addDomains(Arrays.asList("uv.wx", "y.z")); + builder.addDomain("*.wild.card"); builder.setCountry("XX"); builder.setLocality("Testville"); @@ -81,7 +82,7 @@ public class CSRBuilderTest { assertThat(builder.toString(), is("CN=abc.de,C=XX,L=Testville,O=Testing Co," + "OU=Testunit,ST=ABC," - + "DNS=abc.de,DNS=fg.hi,DNS=jklm.no,DNS=pqr.st,DNS=uv.wx,DNS=y.z")); + + "DNS=abc.de,DNS=fg.hi,DNS=jklm.no,DNS=pqr.st,DNS=uv.wx,DNS=y.z,DNS=*.wild.card")); builder.sign(testKey); @@ -103,6 +104,7 @@ public class CSRBuilderTest { builder.addDomain("fg.hi"); builder.addDomains("jklm.no", "pqr.st"); builder.addDomains(Arrays.asList("uv.wx", "y.z")); + builder.addDomain("*.wild.card"); builder.setCountry("XX"); builder.setLocality("Testville"); @@ -112,7 +114,7 @@ public class CSRBuilderTest { assertThat(builder.toString(), is("CN=abc.de,C=XX,L=Testville,O=Testing Co," + "OU=Testunit,ST=ABC," - + "DNS=abc.de,DNS=fg.hi,DNS=jklm.no,DNS=pqr.st,DNS=uv.wx,DNS=y.z")); + + "DNS=abc.de,DNS=fg.hi,DNS=jklm.no,DNS=pqr.st,DNS=uv.wx,DNS=y.z,DNS=*.wild.card")); builder.sign(testEcKey); @@ -149,7 +151,7 @@ public class CSRBuilderTest { assertThat(names.getNames(), arrayContaining(new GeneralNameMatcher("abc.de"), new GeneralNameMatcher("fg.hi"), new GeneralNameMatcher("jklm.no"), new GeneralNameMatcher("pqr.st"), new GeneralNameMatcher("uv.wx"), - new GeneralNameMatcher("y.z"))); + new GeneralNameMatcher("y.z"), new GeneralNameMatcher("*.wild.card"))); } /** diff --git a/src/site/markdown/usage/order.md b/src/site/markdown/usage/order.md index 11b0669a..ce9b9028 100644 --- a/src/site/markdown/usage/order.md +++ b/src/site/markdown/usage/order.md @@ -84,14 +84,30 @@ The CA server may start the validation immediately after `trigger()` is invoked, When the challenge status is `VALID`, you have successfully authorized your domain. -## Deactivate an Authorization +## Wildcard Certificates -It is possible to deactivate an `Authorization`, for example if you sell the associated domain. +You can also generate a wildcard certificate that is valid for all subdomains of a domain, by prefixing the domain name with `*.` (e.g. `*.example.org`). The domain itself is not covered by the wildcard certificate, and also needs to be added to the CSR if necessary. + +You must be able to prove ownership of the domain that you want to order a wildcard certificate for. The corresponding `Authorization` resource only refers to that domain, and does not contain the wildcard notation. + +The following example creates a CSR for `example.org` and `*.example.org`: ```java -auth.deactivate(); +KeyPair domainKeyPair = ... // KeyPair to be used for HTTPS encryption + +CSRBuilder csrb = new CSRBuilder(); +csrb.addDomain("example.org"); // example.org itself, if necessary +csrb.addDomain("*.example.org"); // wildcard for all subdomains +csrb.sign(domainKeyPair); +byte[] csr = csrb.getEncoded(); ``` +In the subsequent authorization process, you would have to prove ownership of the `example.org` domain. + +> __Note:__ Some CAs may reject wildcard certificate orders, or may involve `Challenge`s that are not documented here. Refer to your CA's documentation to find out about the wildcard certificate policy. + +> __Note:__ _acme4j_ accepts all kind of wildcard notations (e.g. `www.*.example.org`, `*.*.example.org`.). However, those notations are not specified and may be rejected by your CA. + ## Pre-Authorize a Domain It is possible to pro-actively authorize a domain. This can be useful to find out what challenges are requested by the CA to authorize a domain, before actually ordering a certificate. It may also help to speed up the ordering process, as already completed authorizations do not need to be completed again when ordering the certificate. @@ -105,21 +121,14 @@ Authorization auth = account.preAuthorizeDomain(String domain); > __Note:__ Some CAs may not offer domain pre-authorization. `preAuthorizeDomain()` will then fail and throw an exception. -## Wildcard Certificates +## Deactivate an Authorization -You can also generate wildcard certificates that are valid for the domain itself, and all of its subdomains: +It is possible to deactivate an `Authorization`, for example if you sell the associated domain. ```java -KeyPair domainKeyPair = ... // KeyPair to be used for HTTPS encryption - -CSRBuilder csrb = new CSRBuilder(); -csrb.addDomain("*.example.org"); // Wildcard -csrb.sign(domainKeyPair); -byte[] csr = csrb.getEncoded(); +auth.deactivate(); ``` -> __Note:__ Some CAs may not accept wildcard certificate orders. Validating wildcard certificates may involve `Challenge`s that are not documented here. Refer to your CA's documentation to find out about the wildcard certificate policy. - ## Restore a Challenge Validating a challenge can take a considerable amount of time and is a candidate for asynchronous execution. This can be a problem if you need to keep the `Challenge` object for a later time or a different Java environment.