mirror of https://github.com/shred/acme4j
Changes for latest draft-ietf-acme-tls-alpn
parent
1cffd3428d
commit
95614e73c5
|
@ -35,9 +35,9 @@ public class TlsAlpn01Challenge extends TokenChallenge {
|
|||
public static final String TYPE = "tls-alpn-01";
|
||||
|
||||
/**
|
||||
* OID of the {@code acmeValidation-v1} extension.
|
||||
* OID of the {@code acmeValidation} extension.
|
||||
*/
|
||||
public static final String ACME_VALIDATION_V1_OID = "1.3.6.1.5.5.7.1.30.1";
|
||||
public static final String ACME_VALIDATION_OID = "1.3.6.1.5.5.7.1.31";
|
||||
|
||||
/**
|
||||
* {@code acme-tls/1} protocol.
|
||||
|
@ -57,10 +57,10 @@ public class TlsAlpn01Challenge extends TokenChallenge {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the value that is to be used as {@code acmeValidation-v1} extension in
|
||||
* Returns the value that is to be used as {@code acmeValidation} extension in
|
||||
* the test certificate.
|
||||
*/
|
||||
public byte[] getAcmeValidationV1() {
|
||||
public byte[] getAcmeValidation() {
|
||||
return sha256hash(getAuthorization());
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ public class TlsAlpn01ChallengeTest {
|
|||
assertThat(challenge.getStatus(), is(Status.PENDING));
|
||||
assertThat(challenge.getToken(), is(TOKEN));
|
||||
assertThat(challenge.getAuthorization(), is(KEY_AUTHORIZATION));
|
||||
assertThat(challenge.getAcmeValidationV1(), is(AcmeUtils.sha256hash(KEY_AUTHORIZATION)));
|
||||
assertThat(challenge.getAcmeValidation(), is(AcmeUtils.sha256hash(KEY_AUTHORIZATION)));
|
||||
|
||||
JSONBuilder response = new JSONBuilder();
|
||||
challenge.prepareResponse(response);
|
||||
|
|
|
@ -106,7 +106,7 @@ public class OrderIT extends PebbleITBase {
|
|||
KeyPair challengeKey = createKeyPair();
|
||||
|
||||
X509Certificate cert = CertificateUtils.createTlsAlpn01Certificate(
|
||||
challengeKey, auth.getDomain(), challenge.getAcmeValidationV1());
|
||||
challengeKey, auth.getDomain(), challenge.getAcmeValidation());
|
||||
|
||||
client.dnsAddARecord(TEST_DOMAIN, getBammBammHostname());
|
||||
client.tlsAlpnAddCertificate(auth.getDomain(), challengeKey.getPrivate(), cert);
|
||||
|
|
|
@ -53,12 +53,12 @@ import org.shredzone.acme4j.challenge.TlsAlpn01Challenge;
|
|||
public final class CertificateUtils {
|
||||
|
||||
/**
|
||||
* The {@code acmeValidation-v1} object identifier.
|
||||
* The {@code acmeValidation} object identifier.
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
public static final ASN1ObjectIdentifier ACME_VALIDATION_V1 =
|
||||
new ASN1ObjectIdentifier(TlsAlpn01Challenge.ACME_VALIDATION_V1_OID).intern();
|
||||
public static final ASN1ObjectIdentifier ACME_VALIDATION =
|
||||
new ASN1ObjectIdentifier(TlsAlpn01Challenge.ACME_VALIDATION_OID).intern();
|
||||
|
||||
private CertificateUtils() {
|
||||
// utility class without constructor
|
||||
|
@ -90,18 +90,18 @@ public final class CertificateUtils {
|
|||
* A domain {@link KeyPair} to be used for the challenge
|
||||
* @param subject
|
||||
* The subject (domain name) that is to be validated
|
||||
* @param acmeValidationV1
|
||||
* @param acmeValidation
|
||||
* The value that is returned by
|
||||
* {@link TlsAlpn01Challenge#getAcmeValidationV1()}
|
||||
* {@link TlsAlpn01Challenge#getAcmeValidation()}
|
||||
* @return Created certificate
|
||||
* @since 2.1
|
||||
*/
|
||||
public static X509Certificate createTlsAlpn01Certificate(KeyPair keypair, String subject, byte[] acmeValidationV1)
|
||||
public static X509Certificate createTlsAlpn01Certificate(KeyPair keypair, String subject, byte[] acmeValidation)
|
||||
throws IOException {
|
||||
Objects.requireNonNull(keypair, "keypair");
|
||||
Objects.requireNonNull(subject, "subject");
|
||||
if (acmeValidationV1 == null || acmeValidationV1.length != 32) {
|
||||
throw new IllegalArgumentException("Bad acmeValidationV1 parameter");
|
||||
if (acmeValidation == null || acmeValidation.length != 32) {
|
||||
throw new IllegalArgumentException("Bad acmeValidation parameter");
|
||||
}
|
||||
|
||||
final long now = System.currentTimeMillis();
|
||||
|
@ -121,7 +121,7 @@ public final class CertificateUtils {
|
|||
gns[0] = new GeneralName(GeneralName.dNSName, subject);
|
||||
certBuilder.addExtension(Extension.subjectAlternativeName, false, new GeneralNames(gns));
|
||||
|
||||
certBuilder.addExtension(ACME_VALIDATION_V1, true, new DEROctetString(acmeValidationV1));
|
||||
certBuilder.addExtension(ACME_VALIDATION, true, new DEROctetString(acmeValidation));
|
||||
|
||||
JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder(signatureAlg);
|
||||
|
||||
|
|
|
@ -105,9 +105,9 @@ public class CertificateUtilsTest {
|
|||
assertThat(cert.getSubjectX500Principal().getName(), is("CN=acme.invalid"));
|
||||
assertThat(getSANs(cert), contains(subject));
|
||||
|
||||
assertThat(cert.getCriticalExtensionOIDs(), hasItem(TlsAlpn01Challenge.ACME_VALIDATION_V1_OID));
|
||||
assertThat(cert.getCriticalExtensionOIDs(), hasItem(TlsAlpn01Challenge.ACME_VALIDATION_OID));
|
||||
|
||||
byte[] encodedExtensionValue = cert.getExtensionValue(TlsAlpn01Challenge.ACME_VALIDATION_V1_OID);
|
||||
byte[] encodedExtensionValue = cert.getExtensionValue(TlsAlpn01Challenge.ACME_VALIDATION_OID);
|
||||
assertThat(encodedExtensionValue, is(notNullValue()));
|
||||
|
||||
try (ASN1InputStream asn = new ASN1InputStream(new ByteArrayInputStream(encodedExtensionValue))) {
|
||||
|
|
|
@ -7,15 +7,15 @@ With the `tls-alpn-01` challenge, you prove to the CA that you are able to contr
|
|||
This challenge is not part of the ACME specifications. It is specified [in a separate IETF document](https://tools.ietf.org/html/draft-ietf-acme-tls-alpn) and is still work in progress.
|
||||
</div>
|
||||
|
||||
`TlsAlpn01Challenge` provides a byte array called `acmeValidationV1`:
|
||||
`TlsAlpn01Challenge` provides a byte array called `acmeValidation`:
|
||||
|
||||
```java
|
||||
TlsAlpn01Challenge challenge = auth.findChallenge(TlsAlpn01Challenge.TYPE);
|
||||
|
||||
byte[] acmeValidationV1 = challenge.getAcmeValidationV1();
|
||||
byte[] acmeValidation = challenge.getAcmeValidation();
|
||||
```
|
||||
|
||||
You need to create a self-signed certificate with the domain to be validated set as the only _Subject Alternative Name_. The `acmeValidationV1` must be set as DER encoded `OCTET STRING` extension with the object id `1.3.6.1.5.5.7.1.30.1`. It is required to set this extension as critical.
|
||||
You need to create a self-signed certificate with the domain to be validated set as the only _Subject Alternative Name_. The `acmeValidation` must be set as DER encoded `OCTET STRING` extension with the object id `1.3.6.1.5.5.7.1.31`. It is required to set this extension as critical.
|
||||
|
||||
After that, configure your web server so it will use this certificate on an incoming TLS request having the SNI `subject` and the ALPN protocol `acme-tls/1`.
|
||||
|
||||
|
@ -26,7 +26,7 @@ String subject = auth.getDomain();
|
|||
KeyPair certKeyPair = KeyPairUtils.createKeyPair(2048);
|
||||
|
||||
X509Certificate cert = CertificateUtils.
|
||||
createTlsAlpn01Certificate(certKeyPair, subject, acmeValidationV1);
|
||||
createTlsAlpn01Certificate(certKeyPair, subject, acmeValidation);
|
||||
```
|
||||
|
||||
Now use `cert` and `certKeyPair` to let your web server respond to TLS requests containing an ALPN extension with the value `acme-tls/1` and a SNI extension containing `subject`.
|
||||
|
|
Loading…
Reference in New Issue