Add a way to revoke a certificate without account key pair

pull/33/head
Richard Körber 2017-07-10 23:13:01 +02:00
parent 8fe25efb83
commit 57e9b593d2
3 changed files with 71 additions and 0 deletions

View File

@ -183,4 +183,23 @@ public class Certificate extends AcmeResource {
}
}
/**
* Revoke a certificate. This call is meant to be used for revoking certificates if
* the account's key pair was lost.
*
* @param session
* {@link Session} to be used. Here you can also generate a session by
* using the key pair that was used for signing the CSR.
* @param cert
* {@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.
*/
public static void revoke(Session session, X509Certificate cert,
RevocationReason reason) throws AcmeException {
new Certificate(session, URI.create(""), null, cert).revoke(reason);
}
}

View File

@ -21,6 +21,7 @@ import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.security.KeyPair;
import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.Instant;
@ -202,6 +203,40 @@ public class CertificateTest {
provider.close();
}
/**
* Test that a certificate can be revoked by its domain key pair.
*/
@Test
public void testRevokeCertificateByKeyPair() throws AcmeException, IOException {
final X509Certificate originalCert = TestUtils.createCertificate();
final KeyPair certKeyPair = TestUtils.createDomainKeyPair();
TestableConnectionProvider provider = new TestableConnectionProvider() {
@Override
public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) {
assertThat(uri, is(resourceUri));
assertThat(claims.toString(), sameJSONAs(getJson("revokeCertificateWithReasonRequest")));
assertThat(session, is(notNullValue()));
assertThat(session.getKeyPair(), is(certKeyPair));
}
@Override
public int accept(int... httpStatus) throws AcmeException {
assertThat(httpStatus, isIntArrayContainingInAnyOrder(HttpURLConnection.HTTP_OK));
return HttpURLConnection.HTTP_OK;
}
};
provider.putTestResource(Resource.REVOKE_CERT, resourceUri);
Session session = provider.createSession();
session.setKeyPair(certKeyPair);
Certificate.revoke(session, originalCert, RevocationReason.KEY_COMPROMISE);
provider.close();
}
/**
* Test that numeric revocation reasons are correctly translated.
*/

View File

@ -135,3 +135,20 @@ Optionally, you can provide a revocation reason that the ACME server may use whe
```java
cert.revoke(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 key pair that was used for signing the CSR. `Certificate` provides a special method for this case.
First, create a new `Session` object, but use _the key pair that was used for siging the CSR_. Now invoke the `revoke()` method and pass the `Session`, the certificate to be revoked, and (optionally) a revocation reason.
```java
KeyPair domainKeyPair = ... // the key pair that was used for signing the CSR
URI acmeServerUri = ... // uri of the ACME server
X509Certificate cert = ... // certificate to revoke
Session session = new Session(acmeServerUri, domainKeyPair);
Certificate.revoke(session, cert, RevocationReason.KEY_COMPROMISE);
```
Note that there is no way to revoke a certificate if you should lose both your account's key pair and your domain's key pair.