From 5c762dfe48c0ba2522aacba2ba22b5f1b20a48fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20K=C3=B6rber?= Date: Sun, 26 Jan 2025 16:01:26 +0100 Subject: [PATCH] Fix spelling errors in documentation --- CONTRIBUTING.md | 2 +- README.md | 4 ++-- src/doc/docs/ca/buypass.md | 2 +- src/doc/docs/ca/google.md | 2 +- src/doc/docs/ca/letsencrypt.md | 2 +- src/doc/docs/ca/pebble.md | 2 +- src/doc/docs/ca/sslcom.md | 2 +- src/doc/docs/ca/zerossl.md | 4 ++-- src/doc/docs/challenge/email-reply-00.md | 6 +++--- src/doc/docs/challenge/http-01.md | 2 +- src/doc/docs/challenge/index.md | 2 +- src/doc/docs/development/challenge.md | 4 ++-- src/doc/docs/development/provider.md | 4 ++-- src/doc/docs/development/testing.md | 2 +- src/doc/docs/example.md | 8 ++++---- src/doc/docs/faq.md | 16 ++++++++-------- src/doc/docs/index.md | 4 ++-- src/doc/docs/migration.md | 24 ++++++++++++------------ src/doc/docs/usage/account.md | 16 ++++++++-------- src/doc/docs/usage/advanced.md | 2 +- src/doc/docs/usage/connecting.md | 2 +- src/doc/docs/usage/debugging.md | 2 +- src/doc/docs/usage/exceptions.md | 2 +- src/doc/docs/usage/index.md | 2 +- src/doc/docs/usage/order.md | 10 +++++----- src/doc/docs/usage/persistence.md | 4 ++-- src/doc/docs/usage/renewal.md | 6 +++--- src/doc/docs/usage/revocation.md | 2 +- 28 files changed, 70 insertions(+), 70 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3a79132e..07e0bd81 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,7 +43,7 @@ Good programming does not end with a clean source code, but should have pretty c * Always put separate concerns into separate commits. * If you have interim commits in your history, squash them with an interactive rebase before sending the pull request. * Use present tense and imperative mood in commit messages ("fix bug #1234", not "fixed bug #1234"). -* Always give meaningful commit messages (not just "bugfix"). +* Always give meaningful commit messages (not just "bug fix"). * The commit message must be concise and should not exceed 50 characters. Further explanations may follow in subsequent lines, with an empty line as separator. * Commits must compile and must not break unit tests. * Do not commit IDE generated files and directories (like `.project` or `.idea`). diff --git a/README.md b/README.md index ab4f7139..fd61bf3b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This is a Java client for the _Automatic Certificate Management Environment_ (AC ACME is a protocol that a certificate authority (CA) and an applicant can use to automate the process of verification and certificate issuance. -This Java client helps connecting to an ACME server, and performing all necessary steps to manage certificates. +This Java client helps to connect to an ACME server, and performing all necessary steps to manage certificates. ## Features @@ -34,7 +34,7 @@ This Java client helps connecting to an ACME server, and performing all necessar ## Usage * See the [online documentation](https://shredzone.org/maven/acme4j/) about how to use _acme4j_. -* For a quick start, have a look at [the source code of an example](https://shredzone.org/maven/acme4j/example.html). +* For a quick start, take a look at [the source code of an example](https://shredzone.org/maven/acme4j/example.html). ## Announcements diff --git a/src/doc/docs/ca/buypass.md b/src/doc/docs/ca/buypass.md index 080729f5..d613f980 100644 --- a/src/doc/docs/ca/buypass.md +++ b/src/doc/docs/ca/buypass.md @@ -1,6 +1,6 @@ # Buypass -Web site: [Buypass](https://buypass.com/) +Website: [Buypass](https://buypass.com/) Available since acme4j 3.5.0 diff --git a/src/doc/docs/ca/google.md b/src/doc/docs/ca/google.md index e88df378..b4d435cd 100644 --- a/src/doc/docs/ca/google.md +++ b/src/doc/docs/ca/google.md @@ -1,6 +1,6 @@ # Google -Web site: [Google Trust Services](https://pki.goog/) +Website: [Google Trust Services](https://pki.goog/) Available since acme4j 3.5.0 diff --git a/src/doc/docs/ca/letsencrypt.md b/src/doc/docs/ca/letsencrypt.md index 193fee54..76b471d3 100644 --- a/src/doc/docs/ca/letsencrypt.md +++ b/src/doc/docs/ca/letsencrypt.md @@ -1,6 +1,6 @@ # Let's Encrypt -Web site: [Let's Encrypt](https://letsencrypt.org) +Website: [Let's Encrypt](https://letsencrypt.org) ## Connection URIs diff --git a/src/doc/docs/ca/pebble.md b/src/doc/docs/ca/pebble.md index 74be243d..17730d30 100644 --- a/src/doc/docs/ca/pebble.md +++ b/src/doc/docs/ca/pebble.md @@ -19,7 +19,7 @@ The Pebble server provides an end-entity certificate for the `localhost` and `pe If your Pebble server can be reached at a different domain (like `pebble.example.com` above), you need to create a correct end-entity certificate on your Pebble server. [See here](https://github.com/letsencrypt/pebble/tree/main/test/certs) for how to use `minica` to create a matching certificate. -Otherwise you will get an `AcmeNetworkException: Network error` that is caused by a `java.io.IOException: No subject alternative DNS name matching [...] found` when trying to access the Pebble server. +Otherwise, you will get an `AcmeNetworkException: Network error` that is caused by a `java.io.IOException: No subject alternative DNS name matching [...] found` when trying to access the Pebble server. If you cannot create a correct end-entity certificate on your Pebble server, you could also disable host name verification on Java side: `-Djdk.internal.httpclient.disableHostnameVerification` diff --git a/src/doc/docs/ca/sslcom.md b/src/doc/docs/ca/sslcom.md index aec2c2a5..27d72a59 100644 --- a/src/doc/docs/ca/sslcom.md +++ b/src/doc/docs/ca/sslcom.md @@ -1,6 +1,6 @@ # SSL.com -Web site: [SSL.com](https://ssl.com) +Website: [SSL.com](https://ssl.com) Available since acme4j 3.2.0. **This provider is experimental!** diff --git a/src/doc/docs/ca/zerossl.md b/src/doc/docs/ca/zerossl.md index b15a375c..68169fac 100644 --- a/src/doc/docs/ca/zerossl.md +++ b/src/doc/docs/ca/zerossl.md @@ -1,6 +1,6 @@ # ZeroSSL -Web site: [ZeroSSL](https://zerossl.com) +Website: [ZeroSSL](https://zerossl.com) Available since acme4j 3.2.0 @@ -8,7 +8,7 @@ Available since acme4j 3.2.0 * `acme://zerossl.com` - Production server -ZeroSSL does not provide a staging server (as of Feburary 2024). +ZeroSSL does not provide a staging server (as of February 2024). ## Note diff --git a/src/doc/docs/challenge/email-reply-00.md b/src/doc/docs/challenge/email-reply-00.md index e709e162..9b7f8bf5 100644 --- a/src/doc/docs/challenge/email-reply-00.md +++ b/src/doc/docs/challenge/email-reply-00.md @@ -24,7 +24,7 @@ However, if `Identifier` objects are needed, use `EmailIdentifier.email()` to ge To generate a CSR, the module provides a `SMIMECSRBuilder` that works similar to the standard `CSRBuilder`, but accepts `EmailIdentifier` objects. -With the `SMIMECSRBuilder.setKeyUsageType()`, the desired usage type of the S/MIME certificate can be selected. By default the certificate can be used both for encryption and signing. However this is just a proposal, and the CA is free to ignore it or return an error if the desired usage type is not supported. +With the `SMIMECSRBuilder.setKeyUsageType()`, the desired usage type of the S/MIME certificate can be selected. By default, the certificate can be used both for encryption and signing. However, this is just a proposal, and the CA is free to ignore it or return an error if the desired usage type is not supported. ## Challenge and Response @@ -49,7 +49,7 @@ After that, the `EmailReply00Challenge` is triggered. The CA now has a proof of ## Response Helper -The response process can be executed programatically, or even manually. To help with the process, `acme4j-smime` provides an `EmailProcessor` that helps you parsing the challenge email, and generate a matching response mail. +The response process can be executed programmatically, or even manually. To help with the process, `acme4j-smime` provides an `EmailProcessor` that helps you to parse the challenge email, and generate a matching response mail. It is basically invoked like this: @@ -90,4 +90,4 @@ Transport.send(response); // send response to the CA challenge.trigger(); // trigger the challenge ``` -If you need more control of the signature verification process, you can use `EmailProcessor.builder()`. It is useful e.g. if you need to use a different truststore, or if your MTA has mangled the incoming message, so a relaxed verification is needed. +If you need more control of the signature verification process, you can use `EmailProcessor.builder()`. It is useful e.g. if you need to use a different trust store, or if your MTA has mangled the incoming message, so a relaxed verification is needed. diff --git a/src/doc/docs/challenge/http-01.md b/src/doc/docs/challenge/http-01.md index a4d3c74f..28c2605f 100644 --- a/src/doc/docs/challenge/http-01.md +++ b/src/doc/docs/challenge/http-01.md @@ -1,6 +1,6 @@ # http-01 Challenge -With the `http-01` challenge, you prove to the CA that you are able to control the web site content of the domain to be authorized, by making a file with a signed content available at a given path. +With the `http-01` challenge, you prove to the CA that you are able to control the website content of the domain to be authorized, by making a file with a signed content available at a given path. `Http01Challenge` provides two strings: diff --git a/src/doc/docs/challenge/index.md b/src/doc/docs/challenge/index.md index f525e2cd..426ea248 100644 --- a/src/doc/docs/challenge/index.md +++ b/src/doc/docs/challenge/index.md @@ -2,7 +2,7 @@ Challenges are used to prove ownership of a domain. -There are different kind of challenges. The most simple is maybe the HTTP challenge, where a file must be made available at the domain that is to be validated. It is assumed that you control the domain if you are able to publish a given file under a given path. +There are different kinds of challenges. The most simple is maybe the HTTP challenge, where a file must be made available at the domain that is to be validated. It is assumed that you control the domain if you are able to publish a given file under a given path. The ACME specifications define these standard challenges: diff --git a/src/doc/docs/development/challenge.md b/src/doc/docs/development/challenge.md index 355b220a..c8f51b03 100644 --- a/src/doc/docs/development/challenge.md +++ b/src/doc/docs/development/challenge.md @@ -10,7 +10,7 @@ If your provider requires a challenge that is too special for generic use, you c Starting with _acme4j_ v2.12, generic challenges can be added globally using Java's `ServiceLoader` mechanism. -Your implementation must provide a challenge provider that implements the `org.shredzone.acme4j.provider.ChallengeProvider` interface and is annotated with a `org.shredzone.acme4j.provider.ChallengeType` annotation giving the name of your challenge. The only method `Challenge create(Login login, JSON data)` must return a new instance of your `Challenge` class which is initalized with the challenge data given in the `data` JSON structure. +Your implementation must provide a challenge provider that implements the `org.shredzone.acme4j.provider.ChallengeProvider` interface and is annotated with a `org.shredzone.acme4j.provider.ChallengeType` annotation giving the name of your challenge. The only method `Challenge create(Login login, JSON data)` must return a new instance of your `Challenge` class which is initialized with the challenge data given in the `data` JSON structure. A simple example of a `ChallengeProvider` is: @@ -42,7 +42,7 @@ After you completed your challenge code, you can send in a pull request and appl These preconditions must be met: * The challenge must be of common interest. If the challenge is only useful to your CA, better publish an own Java package instead. -* The specification of the challenge must be available to the general public. It must be downloadable free of charge and without prior obligation to register. +* The specification of the challenge must be available to the public. It must be downloadable free of charge and without prior obligation to register. * Your source code must be published under the terms of [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0). * You have the permission of all trademark holders involved, to use their trademarks in the source codes, and package names. diff --git a/src/doc/docs/development/provider.md b/src/doc/docs/development/provider.md index 41aa9477..2ff9c716 100644 --- a/src/doc/docs/development/provider.md +++ b/src/doc/docs/development/provider.md @@ -6,7 +6,7 @@ Basically, it is possible to connect to any kind of ACME server just by connecti Session session = new Session("https://api.example.org/directory"); ``` -ACME providers are "plug-ins" to _acme4j_ that are specialized on a single CA. The example above would then look like this (if the CA is supported by _acme4j_): +ACME providers are "plugins" to _acme4j_ that are specialized on a single CA. The example above would then look like this (if the CA is supported by _acme4j_): ```java Session session = new Session("acme://example.org"); @@ -20,7 +20,7 @@ However, it is also possible to adapt the behavior of wide parts of _acme4j_ to A client provider implements the [`AcmeProvider`](../acme4j-client/apidocs/org.shredzone.acme4j/org/shredzone/acme4j/provider/AcmeProvider.html) interface, but usually it is easier to extend [`AbstractAcmeProvider`](../acme4j-client/apidocs/org.shredzone.acme4j/org/shredzone/acme4j/provider/AbstractAcmeProvider.html) and implement only these two methods: -* `accepts(URI)` checks if the client provider is accepting the provided URI. Usually it would be an URI like `acme://example.com`. Note that the `http` and `https` schemes are reserved for the generic provider and cannot be used by other providers. +* `accepts(URI)` checks if the client provider is accepting the provided URI. Usually it would be a URI like `acme://example.com`. Note that the `http` and `https` schemes are reserved for the generic provider and cannot be used by other providers. * `resolve(URI)` parses the URI and returns the corresponding URL of the directory service. The `AcmeProvider` implementation needs to be registered with Java's `ServiceLoader`. In the `META-INF/services` path of your project, create a file `org.shredzone.acme4j.provider.AcmeProvider` and write the fully qualified class name of your implementation into that file. If you use Java modules, there must also be a `provides` section in your `module-info.java`, e.g.: diff --git a/src/doc/docs/development/testing.md b/src/doc/docs/development/testing.md index e31630b5..ced37879 100644 --- a/src/doc/docs/development/testing.md +++ b/src/doc/docs/development/testing.md @@ -17,7 +17,7 @@ If you like to change the default configuration of the integration tests (e.g. b * `bammbammUrl`: URI of the _pebble-challtestsrv_ to connect to. Default: `http://localhost:8055` !!! warning - _pebble-challtestsrv_ is meant for testing purposes only. Only use it in secured testing environments. The server is neither hardened, nor does it offer any kind of authentication. + _pebble-challtestsrv_ is meant for testing purposes only. Only use it in secured testing environments. The server is neither hardened nor does it offer any kind of authentication. ## Boulder diff --git a/src/doc/docs/example.md b/src/doc/docs/example.md index 7ecd7afa..1f61d4e9 100644 --- a/src/doc/docs/example.md +++ b/src/doc/docs/example.md @@ -8,11 +8,11 @@ This chapter contains a copy of the class file, along with explanations about wh - The `ClientTest` is meant to be a simple example and proof of concept. It is not meant for production use as it is. -- The exception handling is very simple. If an exception occurs during the process, the example will fail altogether. A real client should handle exceptions like `AcmeUserActionRequiredException` and `AcmeRateLimitedException` properly, by showing the required user action, or delaying the registration process until the rate limitation has been lifted or the retry time has been reached. +- The exception handling is very simple. If an exception occurs during the process, the example will fail altogether. A real client should handle exceptions like `AcmeUserActionRequiredException` and `AcmeRateLimitedException` properly, by showing the required user action, or delaying the registration process until the rate limitation has been lifted, or the retry time has been reached. - At some places the example synchronously polls the server state. This is sufficient for simple cases, but a more complex client should use timers instead. The client should also make use of the fact that authorizations can be executed in parallel, shortening the certification time for multiple domains. -- I recommend to read at least the chapters about [usage](usage/index.md) and [challenges](challenge/index.md), to learn more about how _acme4j_ and the ACME protocol works. +- I recommend reading at least the chapters about [usage](usage/index.md) and [challenges](challenge/index.md), to learn more about how _acme4j_ and the ACME protocol works. - To make the example easier to understand, I will use the specific datatypes instead of the `var` keyword. @@ -27,7 +27,7 @@ There is one constant that you **must** change in order to make the example work Depending on the requirements of your CA, you might also need to set these constants: * `ACCOUNT_EMAIL`: This is the email address that is connected to your account. The default is `null`, meaning that no email address is set. Some CAs accept that, but otherwise you can set your email address here. -* `EAB_KID`, `EAB_HMAC`: If your CA requires External Account Binding (EAB), it will provide you with a KID and a HMAC pair that is connected to your account. In this case, you must provide both values in the corresponding constants (be careful not to mix them up). Otherwise both constants must be set to `null`, which is the default and disables EAB. +* `EAB_KID`, `EAB_HMAC`: If your CA requires External Account Binding (EAB), it will provide you with a KID and a HMAC pair that is connected to your account. In this case, you must provide both values in the corresponding constants (be careful not to mix them up). Otherwise, both constants must be set to `null`, which is the default and disables EAB. The other constants should work with their default values, but can still be changed if necessary: @@ -188,7 +188,7 @@ private KeyPair loadOrCreateDomainKeyPair() throws IOException { ## Registering an Account -If you does not have an account set up already, you need to create one first. The following method will show a link to the terms of service and ask you to accept it. +If you do not have an account set up already, you need to create one first. The following method will show a link to the terms of service and ask you to accept it. After that, the `AccountBuilder` will create an account using the given account `KeyPair`. It will set an email address if provided. If the CA performs External Account Binding and a KID and HMAC is provided, it is forwarded to the CA. diff --git a/src/doc/docs/faq.md b/src/doc/docs/faq.md index 4d753a8d..490c0369 100644 --- a/src/doc/docs/faq.md +++ b/src/doc/docs/faq.md @@ -29,7 +29,7 @@ You can still revoke certificates without account key pair though, see [here](us ## My `Order` returns status `INVALID`. What has gone wrong? -**Symptom:** Your challenge(s) passed as `VALID`. However when you execute the order, it changes to status `INVALID`. No certificate was issued. +**Symptom:** Your challenge(s) passed as `VALID`. However, when you execute the order, it changes to status `INVALID`. No certificate was issued. **Cause:** There may be multiple reasons for that. It seems that you are still missing steps that are required by the CA before completion. @@ -37,7 +37,7 @@ You can still revoke certificates without account key pair though, see [here](us ## My `Order` seems to be stuck in status `PROCESSING`. What can I do? -**Symptom:** Your challenge(s) passed as `VALID`. However when you execute the order, it seems to be stuck in status `PROCESSING`. +**Symptom:** Your challenge(s) passed as `VALID`. However, when you execute the order, it seems to be stuck in status `PROCESSING`. **Cause:** The CA may have retained your order to carry out background checks. These checks can take hours or even days. Please read the CA documentation for further details. @@ -45,7 +45,7 @@ You can still revoke certificates without account key pair though, see [here](us ## Browsers do not accept my certificate. -**Symptom:** A certificate was successfully issued. However the browser does not accept the certificate, and shows an error that the cert authority is invalid. +**Symptom:** A certificate was successfully issued. However, the browser does not accept the certificate, and shows an error that the cert authority is invalid. **Cause:** This problem occurs when the staging server of a CA is used (e.g. `acme://letsencrypt.org/staging`). The certificate is signed correctly, but the staging issuer certificate is not known to the browser. @@ -69,19 +69,19 @@ You can still revoke certificates without account key pair though, see [here](us ## The S/MIME certificate challenge fails. -**Sympton:** You try to order an S/MIME certificate from a providing CA. However the CA constantly refuses the response e-mail because the contained ACME response is purportedly invalid. +**Symptom:** You try to order an S/MIME certificate from a providing CA. However, the CA constantly refuses the response e-mail because the contained ACME response is purportedly invalid. **Cause:** Unfortunately [RFC 8823](https://tools.ietf.org/html/rfc8823) has an ambiguous specification about how to concatenate the two token parts. The text permits two different interpretations that may give different results. _acme4j_ uses an implementation that corresponds to the [intention of the author of RFC 8823](https://mailarchive.ietf.org/arch/msg/acme/KusfZm3qC50IfcAAuTXtmbFK0KM/). If the CA is implemented following the other interpretation, the ACME e-mail response will not match (see [this issue](https://github.com/shred/acme4j/issues/123)). -**Solution:** It is a difficult situation that is caused by an ambiguous specification, but it is like it is now. Since _acme4j_ follows the intention of the RFC author, I take the position that the _acme4j_ implementation is correct. Please open a bug report at the CA, and refer to [this issue](https://github.com/shred/acme4j/issues/123). If the two tokens are split at a position so the first token won't have trailing base64 padding bits, the CA service can be implemented in a way that is compatible to both interpretations. +**Solution:** It is a difficult situation that is caused by an ambiguous specification, but it is like it is now. Since _acme4j_ follows the intention of the RFC author, I take the position that the _acme4j_ implementation is correct. Please open a bug report at the CA, and refer to [this issue](https://github.com/shred/acme4j/issues/123). If the two tokens are split at a position, so the first token won't have trailing base64 padding bits, the CA service can be implemented in a way that is compatible to both interpretations. ## Suddenly acme4j starts throwing `AcmeUserActionRequiredException` everywhere! How can I fix that? -**Sympton:** Many _acme4j_ methods suddenly throw a `AcmeUserActionRequiredException` after interacting with the server. It is impossible to order certificates. +**Symptom:** Many _acme4j_ methods suddenly throw a `AcmeUserActionRequiredException` after interacting with the server. It is impossible to order certificates. **Cause:** The CA has probably changed its terms of service and wants you to accept them before resuming. -**Solution:** Invoke `AcmeUserActionRequiredException.getInstance()` to get an URL of a web page that describes all further steps to be taken. You might also be able to resolve the issue by logging into your CA's account, but that is up to the CA's discretion. +**Solution:** Invoke `AcmeUserActionRequiredException.getInstance()` to get a URL of a web page that describes all further steps to be taken. You might also be able to resolve the issue by logging into your CA's account, but that is up to the CA's discretion. Unfortunately, manual action is required in any case, there is no way to automate this process. This is an intentional protocol decision, and _acme4j_ is just the messenger. @@ -89,4 +89,4 @@ Unfortunately, manual action is required in any case, there is no way to automat * [Let's Encrypt Documentation](https://letsencrypt.org/docs/) * [Let's Encrypt Community](https://community.letsencrypt.org/) - If the question is _acme4j_ related, please mention it in your post. I don't read the forum every day, but I will answer as soon as I notice it. -* [SSL.com Knowledgebase](https://www.ssl.com/info/) +* [SSL.com Knowledge base](https://www.ssl.com/info/) diff --git a/src/doc/docs/index.md b/src/doc/docs/index.md index cbf53c16..aae9d007 100644 --- a/src/doc/docs/index.md +++ b/src/doc/docs/index.md @@ -4,7 +4,7 @@ A Java client for the _Automatic Certificate Management Environment_ (ACME) prot ACME is a protocol that a certificate authority (CA) and an applicant can use to automate the process of verification and certificate issuance. -This Java client helps connecting to an ACME server, and performing all necessary steps to manage certificates. +This Java client helps to connect to an ACME server, and performing all necessary steps to manage certificates. The source code can be found at [GitHub](https://github.com/shred/acme4j) and is distributed under the terms of [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0). @@ -57,7 +57,7 @@ acme4j-example : This module only contains [an example code](example.md) that demonstrates how to get a certificate with _acme4j_. It is not useful as a dependency in other projects. acme4j-it -: [`acme4j-it`](https://mvnrepository.com/artifact/org.shredzone.acme4j/acme4j-it/latest) mainly serves as integration test suite for _acme4j_ itself. It is not really useful as a dependency in other projects. However if you write own integration tests using [pebble](https://github.com/letsencrypt/pebble) and [pebble-challtestsrv](https://hub.docker.com/r/letsencrypt/pebble-challtestsrv), you may find the [`challtestsrv` configuration client](acme4j-it/apidocs/org.shredzone.acme4j.it/org/shredzone/acme4j/it/BammBammClient.html) useful in your project. +: [`acme4j-it`](https://mvnrepository.com/artifact/org.shredzone.acme4j/acme4j-it/latest) mainly serves as integration test suite for _acme4j_ itself. It is not really useful as a dependency in other projects. However, if you write own integration tests using [pebble](https://github.com/letsencrypt/pebble) and [pebble-challtestsrv](https://hub.docker.com/r/letsencrypt/pebble-challtestsrv), you may find the [`challtestsrv` configuration client](acme4j-it/apidocs/org.shredzone.acme4j.it/org/shredzone/acme4j/it/BammBammClient.html) useful in your project. The Java module name is `org.shredzone.acme4j.it`. diff --git a/src/doc/docs/migration.md b/src/doc/docs/migration.md index 8a96ef99..7e031cac 100644 --- a/src/doc/docs/migration.md +++ b/src/doc/docs/migration.md @@ -4,11 +4,11 @@ This document will help you migrate your code to the latest _acme4j_ version. ## Migration to Version 3.5.0 -- If you use STAR auto renewal certificates, you can now use `Order.getCertificate()` instead of `Order.getAutoRenewalCertificate()` to retrieve the STAR certificate. `Order.getAutoRenewalCertificate()` is marked as deprecated, but still functional. The new method `Order.isAutoRenewalCertificate()` can be used to check if the order resulted in a standard or auto-renewing certificate. +- If you use STAR auto-renewal certificates, you can now use `Order.getCertificate()` instead of `Order.getAutoRenewalCertificate()` to retrieve the STAR certificate. `Order.getAutoRenewalCertificate()` is marked as deprecated, but still functional. The new method `Order.isAutoRenewalCertificate()` can be used to check if the order resulted in a standard or auto-renewing certificate. ## Migration to Version 3.4.0 -- To be futureproof, you should wait for your `Order` resource's state to become `READY` before invoking `Order.execute()`. Most CAs change to the `READY` state immediately, but this behavior is not specified in RFC8555. Future CA implementations may stay in `PENDING` state for a short while, and would return an error if `execute()` is invoked too early. Also see the [example](example.md#the-main-workflow) for how wait for the `READY` state. +- To be future-proof, you should wait for your `Order` resource's state to become `READY` before invoking `Order.execute()`. Most CAs change to the `READY` state immediately, but this behavior is not specified in RFC8555. Future CA implementations may stay in `PENDING` state for a short while, and would return an error if `execute()` is invoked too early. Also see the [example](example.md#the-main-workflow) for how wait for the `READY` state. - There are new methods `waitForCompletion()` and `waitUntilReady()` that will do the synchronous busy wait for the resource state for you. It will remove a lot of boilerplate code that is also bug prone if implemented individually. If you use synchronous polling and waiting (like shown in the example code), I recommend to change to these methods instead of waiting for the correct state yourself. See the [example](example.md) for how to use the new methods. - Marked `update()` (and `AcmeRetryAfterException`) as deprecated now. Please use `fetch()` instead, it returns the retry-after time as `Optional` instead of throwing an `AcmeRetryAfterException`. @@ -36,14 +36,14 @@ Although acme4j has made a major version bump, the migration of your code should What you might also need to know: - A new `AcmeNotSupportedException` is thrown if a feature is not supported by the server. It is a subclass of the `AcmeProtocolException` runtime exception. -- Starting with _acme4j_ v3, we will require the smallest Java SE LTS version that is still receiving premier support according to the [Oracle Java SE Support Roadmap](https://www.oracle.com/java/technologies/java-se-support-roadmap.html). At the time of writing, these are Java 11 and Java 17, so _acme4j_ requires Java 11 starting from now. With the prospected release of Java 21 (LTS) in September 2023, we will move to Java 17, and so on. If you still need Java 8, you can use _acme4j_ v2. However it won't receive updates anymore, except of security related fixes. +- Starting with _acme4j_ v3, we will require the smallest Java SE LTS version that is still receiving premier support according to the [Oracle Java SE Support Roadmap](https://www.oracle.com/java/technologies/java-se-support-roadmap.html). At the time of writing, these are Java 11 and Java 17, so _acme4j_ requires Java 11 starting from now. With the prospected release of Java 21 (LTS) in September 2023, we will move to Java 17, and so on. If you still need Java 8, you can use _acme4j_ v2. However, it won't receive updates anymore, except of security related fixes. - _acme4j_ now uses the new `java.net.http` client. Due to limitations of the API, HTTP errors are only thrown with the error code, but the respective error message is missing. If you checked the error message in your unit tests, be prepared that they might fail now. - acme4j now accepts HTTP gzip compression. It is enabled by default, but if it causes problems or impedes debugging, it can be disabled in the `NetworkSettings` or by setting the `org.shredzone.acme4j.gzip_compression` system property to `false`. - All deprecated methods have been removed. ## Migration to Version 2.16 -- In `acme4j-smime`, the `EmailProcessor.smimeMessage()` method is now deprecated. Use either `EmailProcessor.signedMessage()`, or `EmailProcessor.builder()` if you need custom verification configuration (e.g. an own truststore). +- In `acme4j-smime`, the `EmailProcessor.smimeMessage()` method is now deprecated. Use either `EmailProcessor.signedMessage()`, or `EmailProcessor.builder()` if you need custom verification configuration (e.g. an own trust store). - In `acme4j-smime`, major parts of the S/MIME message verification have been rewritten. The verification is much stricter now, and also supports secured headers in the certificate. Verification might now fail while it was successful in v2.15. Also, exception messages might have changed. ## Migration to Version 2.15 @@ -63,9 +63,9 @@ What you might also need to know: - In a preparation for Java 9 modules, the JSR305 null-safe annotations have been replaced by SpotBugs annotations. This _should_ have no impact on your code, as the method signatures themselves are unchanged. However, the compiler could now complain about some `null` dereferences that have been undetected before. Reason is that JSR305 uses the `javax.annotations` package, which leads to split packages in a Java 9 modular environment. -- When fetching the directory, acme4j now evaluates HTTP caching headers instead of just caching the directory for 1 hour. However, Let's Encrypt explicitly forbids caching, which means that a fresh copy of the directory is now fetched from the server every time it is needed. I don't like it, but it is the RFC conformous behavior. It needs to be [fixed on Let's Encrypt side](https://github.com/letsencrypt/boulder/issues/4814). +- When fetching the directory, acme4j now evaluates HTTP caching headers instead of just caching the directory for 1 hour. However, Let's Encrypt explicitly forbids caching, which means that a fresh copy of the directory is now fetched from the server every time it is needed. I don't like it, but it is the RFC compliant behavior. It needs to be [fixed on Let's Encrypt side](https://github.com/letsencrypt/boulder/issues/4814). -- `AcmeProvider.directory(Session, URI)` is now responsible for maintaining the cache. Implementations can use `Session.setDirectoryExpires()`, `Session.setDirectoryLastModified()`, and the respective getters, for keeping track of the local directory state. `AcmeProvider.directory(Session, URI)` may now return `null`, to indicate that the remote directory was unchanged and the local copy is still valid. It's not permitted to return `null` if `Session.hasDirectory()` returns `false`, though! If your `AcmeProvider` is derived from `AbstractAcmeProvider`, and you haven't overridden the `directory()` method, no migration is necessary. +- `AcmeProvider.directory(Session, URI)` is now responsible for maintaining the cache. Implementations can use `Session.setDirectoryExpires()`, `Session.setDirectoryLastModified()`, and the respective getters, for keeping track of the local directory state. `AcmeProvider.directory(Session, URI)` may now return `null`, to indicate that the remote directory was unchanged, and the local copy is still valid. It's not permitted to return `null` if `Session.hasDirectory()` returns `false`, though! If your `AcmeProvider` is derived from `AbstractAcmeProvider`, and you haven't overridden the `directory()` method, no migration is necessary. ## Migration to Version 2.9 @@ -73,7 +73,7 @@ What you might also need to know: ## Migration to Version 2.8 -- Challenges can now be found by their class type instead of a type string, which makes finding a challenge type safe. I recommend to migrate your code to this new way. The classic way is not deprecated and will not be removed though. Example: +- Challenges can now be found by their class type instead of a type string, which makes finding a challenge type safe. I recommend migrating your code to this new way. The classic way is not deprecated and will not be removed though. Example: ```java Http01Challenge challenge = auth.findChallenge(Http01Challenge.TYPE); // old style: by name @@ -99,15 +99,15 @@ Http01Challenge challenge = auth.findChallenge(Http01Challenge.class); // new s - The GET compatibility mode has been removed. It also means that the `postasget=false` parameter is ignored from now on. If you need it to connect to your ACME server, do not update to this version until your ACME server has been fixed to support ACME draft 15. !!! warning - _acme4j_ before version 2.5 will not work with providers like Let's Encrypt any more! + _acme4j_ before version 2.5 will not work with providers like Let's Encrypt anymore! ## Migration to Version 2.4 - There was a major change in ACME draft 15. If you use _acme4j_ in a common way, it will transparently take care of everything in the background, so you won't even notice the change. - However, if you connect to a different ACME server than Boulder (Let's Encrypt) or Pebble, you may now get strange errors from the server if it does not support the `POST-as-GET` requests of draft 15 yet. In that case, you can add a `postasget=false` parameter to the ACME server URI (e. g. `"https://localhost:15000/dir?postasget=false"`). Note that this is only a temporary workaround. It will be removed in a future version. Ask the server's CA to add support for ACME draft 15. + However, if you connect to a different ACME server than Boulder (Let's Encrypt) or Pebble, you may now get strange errors from the server if it does not support the `POST-as-GET` requests of draft 15 yet. In that case, you can add a `postasget=false` parameter to the ACME server URI (e.g. `"https://localhost:15000/dir?postasget=false"`). Note that this is only a temporary workaround. It will be removed in a future version. Ask the server's CA to add support for ACME draft 15. -- The `AcmeProvider.connect()` method now gets the ACME server URI as parameter. It allows to add query parameters to the server URI that change the behavior of the resulting connection. If you have implemented your own AcmeProvider, just change the method's signature to `Connection connect(URI serverUri)`, and ignore the parameter value. +- The `AcmeProvider.connect()` method now gets the ACME server URI as parameter. It allows adding query parameters to the server URI that change the behavior of the resulting connection. If you have implemented your own AcmeProvider, just change the method's signature to `Connection connect(URI serverUri)`, and ignore the parameter value. ## Migration to Version 2.3 @@ -121,10 +121,10 @@ Http01Challenge challenge = auth.findChallenge(Http01Challenge.class); // new s - This version adds [JSR 305](https://jcp.org/en/jsr/detail?id=305) annotations. If you use a null-safe language like Kotlin, or tools like SpotBugs, your code may fail to compile because of detected possible null pointer dereferences and unclosed streams. These are potential bugs that need to be resolved. -- In _acme4j_'s `JSON` class, all `as...()` getters now expect a value to be present. For optional values, use `JSON.Value.optional()` or `JSON.Value.map()`. This class is rarely used outside of _acme4j_ itself, so you usually won't need to change anything. +- In _acme4j_'s `JSON` class, all `as...()` getters now expect a value to be present. For optional values, use `JSON.Value.optional()` or `JSON.Value.map()`. This class is rarely used outside _acme4j_ itself, so you usually won't need to change anything. ## Migration to Version 2.0 _acme4j_ 2.0 fully supports the ACMEv2 protocol. Sadly, the ACMEv2 protocol is a major change. -There is no easy recipe to migrate your code to _acme4j_ 2.0. I recommend to have a look at the example, and read this documentation. Altogether, it shouldn't be too much work to update your code, though. +There is no easy recipe to migrate your code to _acme4j_ 2.0. I recommend taking a look at the example, and read this documentation. Altogether, it shouldn't be too much work to update your code, though. diff --git a/src/doc/docs/usage/account.md b/src/doc/docs/usage/account.md index 8e08fa06..4b776212 100644 --- a/src/doc/docs/usage/account.md +++ b/src/doc/docs/usage/account.md @@ -7,7 +7,7 @@ Your account requires a key pair. The public key is used to identify your accoun !!! note The private key is never transmitted to the ACME server. -You can use external tools like `openssl` or standard Java methods to create the key pair. A more convenient way is to use the `KeyPairUtils` class. This call generates a RSA key pair with a 2048 bit key: +You can use external tools like `openssl` or standard Java methods to create the key pair. A more convenient way is to use the `KeyPairUtils` class. This call generates an RSA key pair with a 2048-bit key: ```java KeyPair accountKeyPair = KeyPairUtils.createKeyPair(2048); @@ -47,7 +47,7 @@ It is recommended to store the location URL along with your key pair. While this ## External Account Binding -At some CAs, you need to create a customer account on their website first, and associate it with your ACME account and keypair later. The CA indicates that this process is required if `session.getMetadata().isExternalAccountRequired()` returns `true`. +At some CAs, you need to create a customer account on their website first, and associate it with your ACME account and key pair later. The CA indicates that this process is required if `session.getMetadata().isExternalAccountRequired()` returns `true`. In this case, your CA provides you a _Key Identifier_ (or _KID_) and a _MAC Key_ (or _HMAC Key_). You can pass these credentials to the builder using the `withKeyIdentifier()` method: @@ -71,7 +71,7 @@ For your convenience, you can also pass a base64 encoded MAC Key as `String`. ## Login -After creating an account, you need to login into it. You get a `Login` object by providing your account information to the session: +After creating an account, you need to log in into it. You get a `Login` object by providing your account information to the session: ```java KeyPair accountKeyPair = ... // account's key pair @@ -115,7 +115,7 @@ Login login = new AccountBuilder() URL accountLocationUrl = login.getAccountLocation(); ``` -It will return a `Login` object just from your keypair, or throw an error if the key was not known to the server. +It will return a `Login` object just from your key pair, or throw an error if the key was not known to the server. Remember that there is no way to log into your account without the key pair! @@ -133,14 +133,14 @@ account.modify() .commit(); ``` -You can also get the list of contacts via `getContacts()`, and modify or remove contact `URI`s there. However, some CAs do not allow to remove all contacts. +You can also get the list of contacts via `getContacts()`, and modify or remove contact `URI`s there. However, some CAs do not allow removing all contacts. !!! note `AccountBuilder` only accepts contact addresses when a _new account_ is created. To modify an existing account, use `Account.modify()` as described in this section. It is not possible to modify the account using the `AccountBuilder` on an existing account. ## Changing the Account Key -It is recommended to change the account key from time to time, e.g if you suspect that your key has been compromised, or if a staff member with knowledge of the key has left the company. +It is recommended to change the account key from time to time, e.g. if you suspect that your key has been compromised, or if a staff member with knowledge of the key has left the company. To change the key pair that is associated with your account, you can use the `Account.changeKey()` method: @@ -153,11 +153,11 @@ account.changeKey(newKeyPair); After a successful change, all subsequent calls related to this account must use the new key pair. The key is automatically updated on the `Login` that was bound to this `Account` instance, so it can be used further. Other existing `Login` instances to the account need to be recreated. -The old key pair can be disposed of after that. However, better keep a backup of the old key pair until the key change was proven to be successful, by making a subsequent call with the new key pair. Otherwise you might lock yourself out from your account if the key change should have failed silently, for whatever reason. +The old key pair can be disposed of after that. However, better keep a backup of the old key pair until the key change was proven to be successful, by making a subsequent call with the new key pair. Otherwise, you might lock yourself out from your account if the key change should have failed silently, for whatever reason. ## Account Deactivation -You can deactivate your account if you don't need it any more: +You can deactivate your account if you don't need it anymore: ```java account.deactivate(); diff --git a/src/doc/docs/usage/advanced.md b/src/doc/docs/usage/advanced.md index 4de1dc55..fd80049d 100644 --- a/src/doc/docs/usage/advanced.md +++ b/src/doc/docs/usage/advanced.md @@ -44,7 +44,7 @@ The `CSRBuilder` is used internally for creating the CSR, and you can take influ ## Domain Pre-Authorization -It is possible to pro-actively authorize a domain, without ordering a certificate yet. This can be useful to find out what challenges are requested by the CA to authorize a domain. 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 in the near future. +It is possible to proactively authorize a domain, without ordering a certificate yet. This can be useful to find out what challenges are requested by the CA to authorize a domain. 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 in the near future. ```java Account account = ... // your Account object diff --git a/src/doc/docs/usage/connecting.md b/src/doc/docs/usage/connecting.md index 9c9d6d42..381920af 100644 --- a/src/doc/docs/usage/connecting.md +++ b/src/doc/docs/usage/connecting.md @@ -17,7 +17,7 @@ The Session now knows where to locate the service endpoints. However, no actual ## ACME URIs -Such an URI is hard to remember and might even change in the future. For this reason, special ACME connection URIs should be preferred. These special ACME URIs look like this: +Such a URI is hard to remember and might even change in the future. For this reason, special ACME connection URIs should be preferred. These special ACME URIs look like this: ```java Session session = new Session("acme://example.org/staging"); diff --git a/src/doc/docs/usage/debugging.md b/src/doc/docs/usage/debugging.md index 8ddb9de2..969d638b 100644 --- a/src/doc/docs/usage/debugging.md +++ b/src/doc/docs/usage/debugging.md @@ -33,7 +33,7 @@ Android does not log SLF4J output by default. To enable debug logging to logcat, **Do not blindly post debug logs to public bug reports or questions!** -Understanding the debug log output requires some basic knowledge about the [RFC 8555](https://tools.ietf.org/html/rfc8555) protocol. If you need assistance with your problem, don't hesistate to [open an issue](https://github.com/shred/acme4j/issues). +Understanding the debug log output requires some basic knowledge about the [RFC 8555](https://tools.ietf.org/html/rfc8555) protocol. If you need assistance with your problem, don't hesitate to [open an issue](https://github.com/shred/acme4j/issues). ## Example Log Output diff --git a/src/doc/docs/usage/exceptions.md b/src/doc/docs/usage/exceptions.md index a113bac6..c7b9268e 100644 --- a/src/doc/docs/usage/exceptions.md +++ b/src/doc/docs/usage/exceptions.md @@ -56,7 +56,7 @@ An `AcmeServerException` that indicates that the client has insufficient permiss ## AcmeUserActionRequiredException -This `AcmeServerException` is thrown when an user action is required. The most likely reason is that the Terms of Service have been changed and must be confirmed before proceeding. +This `AcmeServerException` is thrown when a user action is required. The most likely reason is that the Terms of Service have been changed and must be confirmed before proceeding. The exception provides a `Problem` object with a detailed reason, a link to a web page with further instructions to be taken by a human, and an optional link to the new Terms of Service. diff --git a/src/doc/docs/usage/index.md b/src/doc/docs/usage/index.md index 65d5134e..041e49a2 100644 --- a/src/doc/docs/usage/index.md +++ b/src/doc/docs/usage/index.md @@ -1,6 +1,6 @@ # How to Use acme4j -_acme4j_ is a client library that helps connecting to ACME servers without worrying about specification details. +_acme4j_ is a client library that helps to connect to ACME servers without worrying about specification details. This is the main part of the documentation about how to use _acme4j_. diff --git a/src/doc/docs/usage/order.md b/src/doc/docs/usage/order.md index e943d16e..fb507d03 100644 --- a/src/doc/docs/usage/order.md +++ b/src/doc/docs/usage/order.md @@ -45,7 +45,7 @@ The `Authorization` instance contains further details about how you can prove th `Authorization.getChallenges()` returns a collection of all `Challenge`s offered by the CA for domain ownership validation. You only need to complete _one_ of them to successfully authorize your domain. You would usually pick the challenge that is best suited for your infrastructure. !!! tip - See [here](../challenge/index.md) for a description of all standard challenges. However, your CA may not offer all of the standard types, and may offer additional, proprietary challenge types. + See [here](../challenge/index.md) for a description of all standard challenges. However, your CA may not offer all the standard types, and may offer additional, proprietary challenge types. The simplest way is to invoke `findChallenge()`, stating the challenge type your system is able to provide (either as challenge name or challenge class type): @@ -54,7 +54,7 @@ Optional challenge = auth.findChallenge(Http01Challenge.TYPE); Optional challenge = auth.findChallenge(Http01Challenge.class); // by type ``` -It returns a properly casted `Challenge` object, or _empty_ if your challenge type was not offered by the CA. In this example, your system choses `Http01Challenge` because it is able to respond to a [http-01](../challenge/http-01.md) challenge. +It returns a properly cast `Challenge` object, or _empty_ if your challenge type was not offered by the CA. In this example, your system chooses `Http01Challenge` because it is able to respond to an [http-01](../challenge/http-01.md) challenge. !!! tip Passing the challenge type is preferred over the challenge name, as type checks are performed at compile time here. Passing in the challenge name might result in a `ClassCastException` at runtime. @@ -83,7 +83,7 @@ This is a very simple example which can be improved in many ways: * Use an asynchronous architecture instead of a blocking `Thread.sleep()`. * Check if `auth.fetch()` returns a retry-after `Instant`, and wait for the next update at least until this moment is reached. See the [example](../example.md) for a simple way to do that. -The CA server may start with the validation immediately after `trigger()` is invoked, so make sure your server is ready to respond to requests before invoking `trigger()`. Otherwise the challenge might fail instantly. +The CA server may start with the validation immediately after `trigger()` is invoked, so make sure your server is ready to respond to requests before invoking `trigger()`. Otherwise, the challenge might fail instantly. Also keep your response available until the status has changed to `VALID` or `INVALID`. The ACME server may check your response multiple times, and from different IPs! If the status gets `VALID` or `INVALID`, the response you have set up before is not needed anymore. It can (and should) be removed. @@ -96,7 +96,7 @@ If your authorization status turned to `VALID`, you have successfully authorized After successfully completing all authorizations, the order needs to be finalized. -First of all, you will need to generate a key pair that is used for certification and encryption of the domain. Similar to the account key pair, you can either use external tool, Java's own crypto framework, or use the [`KeyPairUtils`](../acme4j-client/apidocs/org.shredzone.acme4j.utils/org/shredzone/acme4j/util/KeyPairUtils.html). +First, you will need to generate a key pair that is used for certification and encryption of the domain. Similar to the account key pair, you can either use external tool, Java's own crypto framework, or use the [`KeyPairUtils`](../acme4j-client/apidocs/org.shredzone.acme4j.utils/org/shredzone/acme4j/util/KeyPairUtils.html). !!! tip Never use your account key pair as domain key pair, but always generate separate key pairs! @@ -235,7 +235,7 @@ Order order = account.newOrder() .create(); ``` -The CA can then choose to issue challenges for any of `foo.bar.example.org`, `bar.example.org`, or `example.org`. For each challenge, the related domain can be get via `Authorization.getIdentifier()`. +The CA can then choose to issue challenges for any of `foo.bar.example.org`, `bar.example.org`, or `example.org`. For each challenge, the related domain can be got via `Authorization.getIdentifier()`. `Authorization.isSubdomainAuthAllowed()` will return `true` if that `Authorization` is used to issue subdomain certificates. diff --git a/src/doc/docs/usage/persistence.md b/src/doc/docs/usage/persistence.md index c2afa0da..445351e2 100644 --- a/src/doc/docs/usage/persistence.md +++ b/src/doc/docs/usage/persistence.md @@ -22,7 +22,7 @@ To revive an `AcmeResource` object from its location URL, you can bind it to you * `Login.bindAuthorization()` takes an authorization URL and returns the corresponding `Authorization` object. * `Login.bindCertificate()` takes a certificate URL and returns the corresponding `Certificate` object. * `Login.bindOrder()` takes an order URL and returns the corresponding `Order` object. -* `Login.bindRenewalInfo()` takes an renewal info URL and returns the corresponding `RenewalInfo` object. +* `Login.bindRenewalInfo()` takes a renewal info URL and returns the corresponding `RenewalInfo` object. There are two methods for binding a `Challenge`: @@ -38,7 +38,7 @@ There is no way to bind an `Account`. To retrieve your account resource, simply All resource objects are serializable, so the current state of the object can also be frozen by Java's serialization mechanism. -However the `Login` that the object is bound to is _not_ serialized! This is because in addition to volatile data, the `Login` object also holds a copy of your private key. Not serializing it prevents you from accidentally exposing your private key in a place with lowered access restrictions. +However, the `Login` that the object is bound to is _not_ serialized! This is because in addition to volatile data, the `Login` object also holds a copy of your private key. Not serializing it prevents you from accidentally exposing your private key in a place with lowered access restrictions. After deserialization, an object is not bound to a `Login` yet. It is required to rebind it by invoking the `rebind()` method of the resource object. diff --git a/src/doc/docs/usage/renewal.md b/src/doc/docs/usage/renewal.md index 0c96422c..55944ee2 100644 --- a/src/doc/docs/usage/renewal.md +++ b/src/doc/docs/usage/renewal.md @@ -5,7 +5,7 @@ Certificates are only valid for a limited time, and need to be renewed before ex To read the expiration date of your certificate, use `X509Certificate.getNotAfter()`. The certificate is eligible to be renewed a few days or weeks before its expiry. Check the documentation of your CA about a recommended time window. Also do not postpone the renewal to the last minute, as there can always be unexpected network issues that delay the issuance of a renewed certificate. !!! tip - Some CAs send a notification mail to your account's mail addresses in time before expiration. However you should not rely on those mails, and only use them as an ultimate warning. + Some CAs send a notification mail to your account's mail addresses in time before expiration. However, you should not rely on those mails, and only use them as an ultimate warning. ## How to Renew @@ -15,7 +15,7 @@ There is no special path for renewing a certificate. To renew it, just [order](o _acme4j_ supports the [draft-ietf-acme-ari](https://www.ietf.org/archive/id/draft-ietf-acme-ari-07.html) draft. -You can check if the CA offers renewal information by invoking `Certificate.hasRenewalInfo()`. If it does, you can get a suggested time window for certificate nenewal by invoking `Certificate.getRenewalInfo()`. +You can check if the CA offers renewal information by invoking `Certificate.hasRenewalInfo()`. If it does, you can get a suggested time window for certificate renewal by invoking `Certificate.getRenewalInfo()`. When renewing a certificate, you can use `OrderBuilder.replaces()` to mark your current certificate as the one being replaced. This step is optional though. @@ -69,4 +69,4 @@ To enable this `GET` method, first check if it is offered by the CA, by invoking ### Cancelling Auto-Renewals -Use `Order.cancelAutoRenewal()` to terminate automatical certificate renewals. +Use `Order.cancelAutoRenewal()` to terminate automatic certificate renewals. diff --git a/src/doc/docs/usage/revocation.md b/src/doc/docs/usage/revocation.md index 85b06fc3..0a744ef8 100644 --- a/src/doc/docs/usage/revocation.md +++ b/src/doc/docs/usage/revocation.md @@ -12,7 +12,7 @@ Optionally, you can provide a revocation reason that the ACME server may use whe cert.revoke(RevocationReason.KEY_COMPROMISE); ``` -There are different reasons for a certificate revocation. If you have sold or deleted the associated domain, you should also deactivate the respective `Authorization` using `Authorization.deactivate()`. Otherwise the new owner of the domain might have problems to get a certificate because the domain name is still associated with your account. +There are different reasons for a certificate revocation. If you have sold or deleted the associated domain, you should also deactivate the respective `Authorization` using `Authorization.deactivate()`. Otherwise, the new owner of the domain might have problems to get a certificate because the domain name is still associated with your account. !!! tip It is not documented if the deactivation of an authorization also revokes the related certificate automatically. If in doubt, revoke the certificate yourself before deactivation.