From cda0f4284bb83f110b8bb1f843ecf5a9a425e450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20K=C3=B6rber?= Date: Sat, 12 Jan 2019 13:59:19 +0100 Subject: [PATCH] Revocate when only the account key and certificate is available --- .../org/shredzone/acme4j/Certificate.java | 37 ++++++++++++++++--- src/site/markdown/usage/certificate.md | 13 ++++++- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java index af7364dd..d010f219 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java @@ -147,17 +147,42 @@ public class Certificate extends AcmeResource { * reason. */ public void revoke(@Nullable RevocationReason reason) throws AcmeException { - LOG.debug("revoke"); - URL resUrl = getSession().resourceUrl(Resource.REVOKE_CERT); + revoke(getLogin(), getCertificate(), reason); + } - try (Connection conn = getSession().connect()) { + /** + * Revoke a certificate. This call is meant to be used for revoking certificates if + * only the account's key pair and the certificate itself is available. + * + * @param login + * {@link Login} to the account + * @param cert + * The {@link X509Certificate} to be revoked + * @param reason + * {@link RevocationReason} stating the reason of the revocation that is + * used when generating OCSP responses and CRLs. {@code null} to give no + * reason. + * @since 2.6 + */ + public static void revoke(Login login, X509Certificate cert, @Nullable RevocationReason reason) + throws AcmeException { + LOG.debug("revoke"); + + Session session = login.getSession(); + + URL resUrl = session.resourceUrl(Resource.REVOKE_CERT); + if (resUrl == null) { + throw new AcmeException("Server does not allow certificate revocation"); + } + + try (Connection conn = session.connect()) { JSONBuilder claims = new JSONBuilder(); - claims.putBase64("certificate", getCertificate().getEncoded()); + claims.putBase64("certificate", cert.getEncoded()); if (reason != null) { claims.put("reason", reason.getReasonCode()); } - conn.sendSignedRequest(resUrl, claims, getLogin()); + conn.sendSignedRequest(resUrl, claims, login); } catch (CertificateEncodingException ex) { throw new AcmeProtocolException("Invalid certificate", ex); } @@ -180,7 +205,7 @@ public class Certificate extends AcmeResource { */ public static void revoke(Session session, KeyPair domainKeyPair, X509Certificate cert, @Nullable RevocationReason reason) throws AcmeException { - LOG.debug("revoke immediately"); + LOG.debug("revoke using the domain key pair"); URL resUrl = session.resourceUrl(Resource.REVOKE_CERT); if (resUrl == null) { diff --git a/src/site/markdown/usage/certificate.md b/src/site/markdown/usage/certificate.md index c3716cb6..4f5dc33a 100644 --- a/src/site/markdown/usage/certificate.md +++ b/src/site/markdown/usage/certificate.md @@ -74,6 +74,15 @@ Optionally, you can provide a revocation reason that the ACME server may use whe cert.revoke(RevocationReason.KEY_COMPROMISE); ``` +If you cannot create a `Certificate` object because you don't know the certificate's location URL, you can also use an alternative method that only requires a `Login` and the certificate itself: + +```java +Login login = ... // login to your account +X509Certificate cert = ... // certificate to revoke + +Certificate.revoke(login, cert, RevocationReason.KEY_COMPROMISE); +``` + ## Revocation without Account Key Pair If you have lost your account key, you can still revoke a certificate as long as you still own the domain key pair that was used for signing the CSR. `Certificate` provides a special method for this case. @@ -85,4 +94,6 @@ X509Certificate cert = ... // certificate to revoke Certificate.revoke(session, domainKeyPair, cert, RevocationReason.KEY_COMPROMISE); ``` -Note that there is no way to revoke a certificate if you have lost both your account's key pair and your domain's key pair. +