diff --git a/README.md b/README.md
index 365ad603..85ad248e 100644
--- a/README.md
+++ b/README.md
@@ -26,9 +26,9 @@ If you require Java 8 or Android compatibility, you can use [acme4j v2](https://
## Dependencies
+* [Bouncy Castle](https://www.bouncycastle.org/)
* [jose4j](https://bitbucket.org/b_c/jose4j/wiki/Home)
* [slf4j](http://www.slf4j.org/)
-* For `acme4j-utils`: [Bouncy Castle](https://www.bouncycastle.org/)
* For `acme4j-smime`: [Jakarta Mail](https://eclipse-ee4j.github.io/mail/), [Bouncy Castle](https://www.bouncycastle.org/)
## Usage
diff --git a/acme4j-client/pom.xml b/acme4j-client/pom.xml
index f2a8f4bc..6a950385 100644
--- a/acme4j-client/pom.xml
+++ b/acme4j-client/pom.xml
@@ -57,6 +57,16 @@
jose4j
${jose4j.version}
+
+ org.bouncycastle
+ bcprov-jdk18on
+ ${bouncycastle.version}
+
+
+ org.bouncycastle
+ bcpkix-jdk18on
+ ${bouncycastle.version}
+
org.slf4j
slf4j-api
diff --git a/acme4j-client/src/main/java/module-info.java b/acme4j-client/src/main/java/module-info.java
index e9d9eb04..0a041f4b 100644
--- a/acme4j-client/src/main/java/module-info.java
+++ b/acme4j-client/src/main/java/module-info.java
@@ -18,6 +18,8 @@
module org.shredzone.acme4j {
requires static com.github.spotbugs.annotations;
requires java.net.http;
+ requires org.bouncycastle.pkix;
+ requires org.bouncycastle.provider;
requires org.jose4j;
requires org.slf4j;
@@ -27,6 +29,7 @@ module org.shredzone.acme4j {
exports org.shredzone.acme4j.exception;
exports org.shredzone.acme4j.provider;
exports org.shredzone.acme4j.toolbox;
+ exports org.shredzone.acme4j.util;
uses org.shredzone.acme4j.provider.AcmeProvider;
uses org.shredzone.acme4j.provider.ChallengeProvider;
diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java b/acme4j-client/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java
similarity index 100%
rename from acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java
rename to acme4j-client/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java
diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java b/acme4j-client/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java
similarity index 100%
rename from acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java
rename to acme4j-client/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java
diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/KeyPairUtils.java b/acme4j-client/src/main/java/org/shredzone/acme4j/util/KeyPairUtils.java
similarity index 100%
rename from acme4j-utils/src/main/java/org/shredzone/acme4j/util/KeyPairUtils.java
rename to acme4j-client/src/main/java/org/shredzone/acme4j/util/KeyPairUtils.java
diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/util/package-info.java
similarity index 100%
rename from acme4j-utils/src/main/java/org/shredzone/acme4j/util/package-info.java
rename to acme4j-client/src/main/java/org/shredzone/acme4j/util/package-info.java
diff --git a/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CSRBuilderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/util/CSRBuilderTest.java
similarity index 100%
rename from acme4j-utils/src/test/java/org/shredzone/acme4j/util/CSRBuilderTest.java
rename to acme4j-client/src/test/java/org/shredzone/acme4j/util/CSRBuilderTest.java
diff --git a/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java
similarity index 100%
rename from acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java
rename to acme4j-client/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java
diff --git a/acme4j-utils/src/test/java/org/shredzone/acme4j/util/KeyPairUtilsTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/util/KeyPairUtilsTest.java
similarity index 100%
rename from acme4j-utils/src/test/java/org/shredzone/acme4j/util/KeyPairUtilsTest.java
rename to acme4j-client/src/test/java/org/shredzone/acme4j/util/KeyPairUtilsTest.java
diff --git a/acme4j-example/pom.xml b/acme4j-example/pom.xml
index 5bc6dee5..d51d761c 100644
--- a/acme4j-example/pom.xml
+++ b/acme4j-example/pom.xml
@@ -59,11 +59,6 @@
acme4j-client
${project.version}
-
- org.shredzone.acme4j
- acme4j-utils
- ${project.version}
-
org.slf4j
slf4j-simple
diff --git a/acme4j-example/src/main/java/module-info.java b/acme4j-example/src/main/java/module-info.java
index eaf613e1..c025aa7a 100644
--- a/acme4j-example/src/main/java/module-info.java
+++ b/acme4j-example/src/main/java/module-info.java
@@ -14,7 +14,6 @@
module org.shredzone.acme4j.example {
requires org.shredzone.acme4j;
- requires org.shredzone.acme4j.utils;
requires java.desktop;
diff --git a/acme4j-it/pom.xml b/acme4j-it/pom.xml
index 7c6ee481..423d86a0 100644
--- a/acme4j-it/pom.xml
+++ b/acme4j-it/pom.xml
@@ -173,11 +173,6 @@
acme4j-client
${project.version}
-
- org.shredzone.acme4j
- acme4j-utils
- ${project.version}
-
org.apache.httpcomponents
diff --git a/acme4j-it/src/main/java/module-info.java b/acme4j-it/src/main/java/module-info.java
index eda2402e..0019d587 100644
--- a/acme4j-it/src/main/java/module-info.java
+++ b/acme4j-it/src/main/java/module-info.java
@@ -14,7 +14,6 @@
module org.shredzone.acme4j.it {
requires org.shredzone.acme4j;
- requires org.shredzone.acme4j.utils;
requires com.github.spotbugs.annotations;
requires org.apache.httpcomponents.httpclient;
diff --git a/acme4j-smime/pom.xml b/acme4j-smime/pom.xml
index d169bba2..c9cbd9ea 100644
--- a/acme4j-smime/pom.xml
+++ b/acme4j-smime/pom.xml
@@ -34,11 +34,6 @@
acme4j-client
${project.version}
-
- org.shredzone.acme4j
- acme4j-utils
- ${project.version}
-
org.bouncycastle
bcprov-jdk18on
diff --git a/acme4j-smime/src/main/java/module-info.java b/acme4j-smime/src/main/java/module-info.java
index df84b263..a1e352e9 100644
--- a/acme4j-smime/src/main/java/module-info.java
+++ b/acme4j-smime/src/main/java/module-info.java
@@ -17,7 +17,6 @@
*/
module org.shredzone.acme4j.smime {
requires org.shredzone.acme4j;
- requires org.shredzone.acme4j.utils;
requires transitive jakarta.mail;
requires static com.github.spotbugs.annotations;
diff --git a/acme4j-utils/pom.xml b/acme4j-utils/pom.xml
deleted file mode 100644
index 4a468a19..00000000
--- a/acme4j-utils/pom.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
- 4.0.0
-
-
- org.shredzone.acme4j
- acme4j
- 3.0.0-SNAPSHOT
-
-
- acme4j-utils
-
- acme4j Utils
- acme4j utilities
-
-
-
- org.shredzone.acme4j
- acme4j-client
- ${project.version}
-
-
- org.bouncycastle
- bcprov-jdk18on
- ${bouncycastle.version}
-
-
- org.bouncycastle
- bcpkix-jdk18on
- ${bouncycastle.version}
-
-
- org.slf4j
- slf4j-api
- ${slf4j.version}
-
-
-
-
diff --git a/acme4j-utils/src/main/java/.gitignore b/acme4j-utils/src/main/java/.gitignore
deleted file mode 100644
index e69de29b..00000000
diff --git a/acme4j-utils/src/main/java/module-info.java b/acme4j-utils/src/main/java/module-info.java
deleted file mode 100644
index 553309de..00000000
--- a/acme4j-utils/src/main/java/module-info.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * acme4j - Java ACME client
- *
- * Copyright (C) 2020 Richard "Shred" Körber
- * http://acme4j.shredzone.org
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-/**
- * This module contains a collection of utility classes. All of them require Bouncy Castle
- * to be added as security provider.
- */
-module org.shredzone.acme4j.utils {
- requires org.shredzone.acme4j;
-
- requires static com.github.spotbugs.annotations;
- requires org.bouncycastle.pkix;
- requires org.bouncycastle.provider;
-
- exports org.shredzone.acme4j.util;
-}
diff --git a/acme4j-utils/src/main/resources/.gitignore b/acme4j-utils/src/main/resources/.gitignore
deleted file mode 100644
index e69de29b..00000000
diff --git a/acme4j-utils/src/test/java/.gitignore b/acme4j-utils/src/test/java/.gitignore
deleted file mode 100644
index e69de29b..00000000
diff --git a/acme4j-utils/src/test/resources/.gitignore b/acme4j-utils/src/test/resources/.gitignore
deleted file mode 100644
index e69de29b..00000000
diff --git a/acme4j-utils/src/test/resources/cert.pem b/acme4j-utils/src/test/resources/cert.pem
deleted file mode 100644
index 6981323c..00000000
--- a/acme4j-utils/src/test/resources/cert.pem
+++ /dev/null
@@ -1,20 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDVzCCAj+gAwIBAgIJAM4KDTzb0Y7NMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNV
-BAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQg
-Q29tcGFueSBMdGQwHhcNMTUxMjEwMDAxMTA4WhcNMjUxMjA3MDAxMTA4WjBCMQsw
-CQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZh
-dWx0IENvbXBhbnkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
-r0g3w4C8xbj/5lzJiDxk0HkEJeZeyruq+0AzOPMigJZ7zxZtX/KUxOIHrQ4qjcFh
-l0DmQImoM0wESU+kcsjAHCx8E1lgRVlVsMfLAQPHkg5UybqfadzKT3ALcSD+9F9m
-VIP6liC/6KzLTASmx6zM7j92KTl1ArObZr5mh0jvSNORrMhEC4Byn3+NTxjuHON1
-rWppCMwpeNNhFzaAig3O8PY8IyaLXNP2Ac5pXn0iW16S+Im9by7751UeW5a7Dznm
-uMEM+WY640ffJDQ4+I64H403uAgvvSu+BGw8SEEZGuBCxoCnG1g6y6OvJyN5TgqF
-dGosAfm1u+/MP1seoPdpBQIDAQABo1AwTjAdBgNVHQ4EFgQUrie5ZLOrA/HuhW1b
-/CHjzEvj34swHwYDVR0jBBgwFoAUrie5ZLOrA/HuhW1b/CHjzEvj34swDAYDVR0T
-BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAkSOP0FUgIIUeJTObgXrenHzZpLAk
-qXi37dgdYuPhNveo3agueP51N7yIoh6YGShiJ73Rvr+lVYTwFXStrLih1Wh3tWvk
-sMxnvocgd7l6USRb5/AgH7eHeFK4DoCAak2hUAcCLDRJN3XMhNLpyJhw7GJxowVI
-GUlxcW5Asrmh9qflfyMyjripTP3CdHobmNcNHyScjNncKj37m8vomel9acekTtDl
-2Ci7nLdE+3VqQCXMIfLiF3PO0gGpKei0RuVCSOG6W83zVInCPd/l3aluSR+f/VZl
-k8KGQ4As4uTQi89j+J1YepzG0ASMZpjVbXeIg5QBAywVxBh5XVTz37KN8A==
------END CERTIFICATE-----
diff --git a/pom.xml b/pom.xml
index 3835d945..c313539e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,7 +62,6 @@
acme4j-client
- acme4j-utils
acme4j-smime
acme4j-example
acme4j-it
diff --git a/src/doc/docs/challenge/tls-alpn-01.md b/src/doc/docs/challenge/tls-alpn-01.md
index 7e30a401..bed1bb4b 100644
--- a/src/doc/docs/challenge/tls-alpn-01.md
+++ b/src/doc/docs/challenge/tls-alpn-01.md
@@ -15,7 +15,7 @@ You need to create a self-signed certificate with the domain to be validated set
After that, configure your web server so it will use this certificate on an incoming TLS request having the SNI `identifier` and the ALPN protocol `acme-tls/1`.
-The `TlsAlpn01Challenge` class does not generate a self-signed certificate for you, as it would require _Bouncy Castle_. However, there is a utility method in the _acme4j-utils_ module for this use case:
+The `TlsAlpn01Challenge` class does not generate a self-signed certificate for you, as it would require _Bouncy Castle_. However, there is a utility method for this use case:
```java
KeyPair certKeyPair = KeyPairUtils.createKeyPair(2048);
diff --git a/src/doc/docs/example.md b/src/doc/docs/example.md
index 4d4abd52..a08f48be 100644
--- a/src/doc/docs/example.md
+++ b/src/doc/docs/example.md
@@ -50,7 +50,7 @@ public static void main(String... args) {
```
!!! note
- As the example makes use of the `acme4j-utils` module for generating key pairs and the CSR, the `BouncyCastleProvider` needs to be added as security provider.
+ The example requires the `BouncyCastleProvider` to be added as security provider.
## The Main Workflow
diff --git a/src/doc/docs/index.md b/src/doc/docs/index.md
index a899c42f..fdf4e2e5 100644
--- a/src/doc/docs/index.md
+++ b/src/doc/docs/index.md
@@ -30,9 +30,9 @@ If you require Java 8 or Android compatibility, you can use [acme4j v2](https://
## Dependencies
+* [Bouncy Castle](https://www.bouncycastle.org/)
* [jose4j](https://bitbucket.org/b_c/jose4j/wiki/Home)
* [slf4j](http://www.slf4j.org/)
-* For `acme4j-utils`: [Bouncy Castle](https://www.bouncycastle.org/)
* For `acme4j-smime`: [Jakarta Mail](https://eclipse-ee4j.github.io/mail/), [Bouncy Castle](https://www.bouncycastle.org/)
## Quick Start
@@ -44,22 +44,17 @@ There is an [example source code](example.md) included in this project. It gives
_acme4j_ consists of five modules. All modules are [available at Maven Central](https://mvnrepository.com/artifact/org.shredzone.acme4j) and can easily be added to the dependency list of your project. You can also download the jar files [at GitHub](https://github.com/shred/acme4j/releases/latest).
acme4j-client
-: [`acme4j-client`](https://mvnrepository.com/artifact/org.shredzone.acme4j/acme4j-client/latest) is the main module. It contains everything that is required to get certificates for domains. It only requires [jose4j](https://bitbucket.org/b_c/jose4j) and [slf4j](https://www.slf4j.org/).
+: [`acme4j-client`](https://mvnrepository.com/artifact/org.shredzone.acme4j/acme4j-client/latest) is the main module. It contains everything that is required to get certificates for domains.
The Java module name is `org.shredzone.acme4j`.
-acme4j-utils
-: [`acme4j-utils`](https://mvnrepository.com/artifact/org.shredzone.acme4j/acme4j-utils/latest) contains utility classes for creating key pairs, CSRs, and certificates. It requires [Bouncy Castle](https://www.bouncycastle.org/java.html) though.
-
- The Java module name is `org.shredzone.acme4j.utils`.
-
acme4j-smime
: [`acme4j-smime`](https://mvnrepository.com/artifact/org.shredzone.acme4j/acme4j-smime/latest) contains the [RFC 8823](https://tools.ietf.org/html/rfc8823) implementation for ordering S/MIME certificates. It requires [Bouncy Castle](https://www.bouncycastle.org/java.html) and a `javax.mail` implementation.
The Java module name is `org.shredzone.acme4j.smime`.
acme4j-example
-: This module only contains [an example code](example.md) that demonstrates how to get a certificate with _acme4j_. It depends on `acme4j-client` and `acme4j-utils`. It is not useful as a dependency in other projects.
+: 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.
diff --git a/src/doc/docs/migration.md b/src/doc/docs/migration.md
index e2fe2e63..da54b3ca 100644
--- a/src/doc/docs/migration.md
+++ b/src/doc/docs/migration.md
@@ -4,7 +4,14 @@ This document will help you migrate your code to the latest _acme4j_ version.
## Migration to Version 3.0.0
+- The `acme4j-utils` module has been removed, and its classes moved into `acme4j-client` module. If you have used it before, just remove the dependency. If your project has a `module-info.java` file, remember to remove the `requires org.shredzone.acme4j.utils` line there as well. If you haven't used the module before: `acme4j-client` now depends on Bouncy Castle, so you might need to register it as security provider at the start of your code:
+ ```java
+ Security.addProvider(new BouncyCastleProvider());
+ ```
- All `@Nullable` return values have been reviewed. Collections may now be empty, but never `null`. Most of the other return values are now either `Optional`, or throwing an exception if more reasonable. If your code fails to compile because the return type has changed to `Optional`, you can simply add `.orElse(null)` to restore the old behavior. But often your code will reveal a better way to handle the former `null` pointer instead.
+
+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 moment 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 start to require Java 17, and so on. If you still need Java 8, you can use _acme4j_ v2, which will receive bugfixes until September 2023.
- Changed to `java.net.http` client. Due to limitations of the API, HTTP errors are only thrown with the error code, but not with the error message. If you checked the message in unit tests, be prepared that the error message might have changed.
diff --git a/src/doc/docs/usage/account.md b/src/doc/docs/usage/account.md
index 3edd214b..2ad02233 100644
--- a/src/doc/docs/usage/account.md
+++ b/src/doc/docs/usage/account.md
@@ -13,7 +13,7 @@ After the CA has created your account, it returns an account URL. You will need
You can use external tools like `openssl` or standard Java methods to create a key pair.
-A more convenient way is to use the `KeyPairUtils` class in the `acme4j-utils` module. This call generates a RSA key pair with a 2048 bit key:
+A more convenient way is to use the `KeyPairUtils` class. This call generates a RSA key pair with a 2048 bit key:
```java
KeyPair accountKeyPair = KeyPairUtils.createKeyPair(2048);
diff --git a/src/doc/docs/usage/order.md b/src/doc/docs/usage/order.md
index 7a4d6906..2572b965 100644
--- a/src/doc/docs/usage/order.md
+++ b/src/doc/docs/usage/order.md
@@ -77,7 +77,7 @@ The response you have set up before is not needed any more. You can (and should)
After successfully completing all authorizations, the order needs to be finalized by providing PKCS#10 CSR file. A single domain may be set as _Common Name_. Multiple domains must be provided as _Subject Alternative Name_. You must provide exactly the domains that you had passed to the `order()` method above, otherwise the finalization will fail. It depends on the CA if other CSR properties (_Organization_, _Organization Unit_ etc.) are accepted. Some may require these properties to be set, while others may ignore them when generating the certificate.
-CSR files can be generated with command line tools like `openssl`. Unfortunately the standard Java does not offer classes for that, so you'd have to resort to [Bouncy Castle](http://www.bouncycastle.org/java.html) if you want to create a CSR programmatically. In the `acme4j-utils` module, there is a [`CSRBuilder`](../acme4j-utils/apidocs/org.shredzone.acme4j.utils/org/shredzone/acme4j/util/CSRBuilder.html) for your convenience. You can also use [`KeyPairUtils`](../acme4j-utils/apidocs/org.shredzone.acme4j.utils/org/shredzone/acme4j/util/KeyPairUtils.html) for generating a new key pair for your domain.
+CSR files can be generated with command line tools like `openssl`. Unfortunately the standard Java does not offer classes for that, so you'd have to resort to [Bouncy Castle](http://www.bouncycastle.org/java.html) if you want to create a CSR programmatically. There is a [`CSRBuilder`](../acme4j-client/apidocs/org.shredzone.acme4j.utils/org/shredzone/acme4j/util/CSRBuilder.html) for your convenience. You can also use [`KeyPairUtils`](../acme4j-client/apidocs/org.shredzone.acme4j.utils/org/shredzone/acme4j/util/KeyPairUtils.html) for generating a new key pair for your domain.
!!! tip
Never use your account key pair as domain key pair, but always generate separate key pairs!
diff --git a/src/doc/mkdocs.yml b/src/doc/mkdocs.yml
index 9f43df25..434c7f6b 100644
--- a/src/doc/mkdocs.yml
+++ b/src/doc/mkdocs.yml
@@ -20,7 +20,6 @@ nav:
- 'example.md'
- JavaDocs:
- 'acme4j-client': acme4j-client/apidocs/index.html
- - 'acme4j-utils': acme4j-utils/apidocs/index.html
- 'acme4j-smime': acme4j-smime/apidocs/index.html
- 'acme4j-it': acme4j-it/apidocs/index.html
- Usage: