mirror of https://github.com/shred/acme4j
Set a RevocationReason on certificate revocation
parent
78cb7259d4
commit
42e94125d8
|
@ -148,6 +148,18 @@ public class Certificate extends AcmeResource {
|
|||
* Revokes this certificate.
|
||||
*/
|
||||
public void revoke() throws AcmeException {
|
||||
revoke(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revokes this certificate.
|
||||
*
|
||||
* @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 void revoke(RevocationReason reason) throws AcmeException {
|
||||
LOG.debug("revoke");
|
||||
URI resUri = getSession().resourceUri(Resource.REVOKE_CERT);
|
||||
if (resUri == null) {
|
||||
|
@ -162,6 +174,9 @@ public class Certificate extends AcmeResource {
|
|||
ClaimBuilder claims = new ClaimBuilder();
|
||||
claims.putResource(Resource.REVOKE_CERT);
|
||||
claims.putBase64("certificate", cert.getEncoded());
|
||||
if (reason != null) {
|
||||
claims.put("reason", reason.getReasonCode());
|
||||
}
|
||||
|
||||
int rc = conn.sendSignedRequest(resUri, claims, getSession());
|
||||
if (rc != HttpURLConnection.HTTP_OK) {
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* acme4j - Java ACME client
|
||||
*
|
||||
* Copyright (C) 2016 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.
|
||||
*/
|
||||
package org.shredzone.acme4j;
|
||||
|
||||
/**
|
||||
* Enumeration of revocation reasons.
|
||||
*
|
||||
* @see <a href="https://tools.ietf.org/html/rfc5280#section-5.3.1">RFC 5280 Section
|
||||
* 5.3.1</a>
|
||||
* @author Richard "Shred" Körber
|
||||
*/
|
||||
public enum RevocationReason {
|
||||
|
||||
UNSPECIFIED(0),
|
||||
KEY_COMPROMISE(1),
|
||||
CA_COMPROMISE(2),
|
||||
AFFILIATION_CHANGED(3),
|
||||
SUPERSEDED(4),
|
||||
CESSATION_OF_OPERATION(5),
|
||||
CERTIFICATE_HOLD(6),
|
||||
REMOVE_FROM_CRL(8),
|
||||
PRIVILEGE_WITHDRAWN(9),
|
||||
AA_COMPROMISE(10);
|
||||
|
||||
/**
|
||||
* Returns the {@link RevocationReason} that matches the reason code.
|
||||
*
|
||||
* @param reasonCode
|
||||
* Reason code as defined in RFC 5280
|
||||
* @return Matching {@link RevocationReason}, or {@code null} if not known
|
||||
*/
|
||||
public static RevocationReason code(int reasonCode) {
|
||||
for (RevocationReason rr : values()) {
|
||||
if (rr.reasonCode == reasonCode) {
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final int reasonCode;
|
||||
|
||||
private RevocationReason(int reasonCode) {
|
||||
this.reasonCode = reasonCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reason code as defined in RFC 5280.
|
||||
*/
|
||||
public int getReasonCode() {
|
||||
return reasonCode;
|
||||
}
|
||||
|
||||
}
|
|
@ -109,4 +109,29 @@ public class CertificateTest {
|
|||
provider.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that a certificate can be revoked with reason.
|
||||
*/
|
||||
@Test
|
||||
public void testRevokeCertificateWithReason() throws AcmeException, IOException {
|
||||
final X509Certificate originalCert = TestUtils.createCertificate();
|
||||
|
||||
TestableConnectionProvider provider = new TestableConnectionProvider() {
|
||||
@Override
|
||||
public int sendSignedRequest(URI uri, ClaimBuilder claims, Session session) {
|
||||
assertThat(uri, is(resourceUri));
|
||||
assertThat(claims.toString(), sameJSONAs(getJson("revokeCertificateWithReasonRequest")));
|
||||
assertThat(session, is(notNullValue()));
|
||||
return HttpURLConnection.HTTP_OK;
|
||||
}
|
||||
};
|
||||
|
||||
provider.putTestResource(Resource.REVOKE_CERT, resourceUri);
|
||||
|
||||
Certificate cert = new Certificate(provider.createSession(), locationUri, null, originalCert);
|
||||
cert.revoke(RevocationReason.KEY_COMPROMISE);
|
||||
|
||||
provider.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -138,6 +138,13 @@ revokeCertificateRequest = \
|
|||
"resource":"revoke-cert"\
|
||||
}
|
||||
|
||||
revokeCertificateWithReasonRequest = \
|
||||
{\
|
||||
"certificate": "MIIDVzCCAj-gAwIBAgIJAM4KDTzb0Y7NMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQwHhcNMTUxMjEwMDAxMTA4WhcNMjUxMjA3MDAxMTA4WjBCMQswCQYDVQQGEwJYWDEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRwwGgYDVQQKDBNEZWZhdWx0IENvbXBhbnkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr0g3w4C8xbj_5lzJiDxk0HkEJeZeyruq-0AzOPMigJZ7zxZtX_KUxOIHrQ4qjcFhl0DmQImoM0wESU-kcsjAHCx8E1lgRVlVsMfLAQPHkg5UybqfadzKT3ALcSD-9F9mVIP6liC_6KzLTASmx6zM7j92KTl1ArObZr5mh0jvSNORrMhEC4Byn3-NTxjuHON1rWppCMwpeNNhFzaAig3O8PY8IyaLXNP2Ac5pXn0iW16S-Im9by7751UeW5a7DznmuMEM-WY640ffJDQ4-I64H403uAgvvSu-BGw8SEEZGuBCxoCnG1g6y6OvJyN5TgqFdGosAfm1u-_MP1seoPdpBQIDAQABo1AwTjAdBgNVHQ4EFgQUrie5ZLOrA_HuhW1b_CHjzEvj34swHwYDVR0jBBgwFoAUrie5ZLOrA_HuhW1b_CHjzEvj34swDAYDVR0TBAUwAwEB_zANBgkqhkiG9w0BAQsFAAOCAQEAkSOP0FUgIIUeJTObgXrenHzZpLAkqXi37dgdYuPhNveo3agueP51N7yIoh6YGShiJ73Rvr-lVYTwFXStrLih1Wh3tWvksMxnvocgd7l6USRb5_AgH7eHeFK4DoCAak2hUAcCLDRJN3XMhNLpyJhw7GJxowVIGUlxcW5Asrmh9qflfyMyjripTP3CdHobmNcNHyScjNncKj37m8vomel9acekTtDl2Ci7nLdE-3VqQCXMIfLiF3PO0gGpKei0RuVCSOG6W83zVInCPd_l3aluSR-f_VZlk8KGQ4As4uTQi89j-J1YepzG0ASMZpjVbXeIg5QBAywVxBh5XVTz37KN8A",\
|
||||
"resource":"revoke-cert",\
|
||||
"reason": 1\
|
||||
}
|
||||
|
||||
authorizationChallenges = \
|
||||
{\
|
||||
"challenges": [\
|
||||
|
|
|
@ -102,3 +102,9 @@ To revoke a certificate, just invoke the respective method:
|
|||
```java
|
||||
cert.revoke();
|
||||
```
|
||||
|
||||
Optionally, you can provide a revocation reason that the ACME server may use when generating OCSP responses and CRLs.
|
||||
|
||||
```java
|
||||
cert.revoke(RevocationReason.KEY_COMPROMISE);
|
||||
```
|
||||
|
|
Loading…
Reference in New Issue