From 7b6af21cd1b6742aa3e580f1f2c6df32cbcf1c46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20K=C3=B6rber?= Date: Sat, 26 Dec 2015 12:40:37 +0100 Subject: [PATCH] Make CertificateUtils.createTlsSniCertificate more useful for TLS-SNI challenge --- .../shredzone/acme4j/util/CertificateUtils.java | 7 +++---- .../acme4j/util/CertificateUtilsTest.java | 10 +++++++--- src/site/markdown/challenge/tls-sni.md | 17 +++++++++++++++-- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java index 189c4868..11e58ba5 100644 --- a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java +++ b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java @@ -95,19 +95,18 @@ public final class CertificateUtils { * Creates a self-signed {@link X509Certificate} that can be used for * {@link TlsSniChallenge}. The certificate is valid for 7 days. * + * @param keypair + * A domain {@link KeyPair} to be used for the challenge * @param subject * Subject to create a certificate for * @return Created certificate */ - public static X509Certificate createTlsSniCertificate(String subject) throws IOException { - final int certSize = 2048; + public static X509Certificate createTlsSniCertificate(KeyPair keypair, String subject) throws IOException { final long now = System.currentTimeMillis(); final long validSpanMs = 7 * 24 * 60 * 60 * 1000L; final String signatureAlg = "SHA256withRSA"; try { - KeyPair keypair = KeyPairUtils.createKeyPair(certSize); - X500Name issuer = new X500Name("CN=acme.invalid"); BigInteger serial = BigInteger.valueOf(now); Date notBefore = new Date(now); diff --git a/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java b/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java index a95917df..13502b8f 100644 --- a/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java +++ b/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java @@ -20,6 +20,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.security.KeyPair; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.CertificateParsingException; @@ -84,17 +85,20 @@ public class CertificateUtilsTest { } /** - * Test if {@link CertificateUtils#createTlsSniCertificate(String)} creates a + * Test if {@link CertificateUtils#createTlsSniCertificate(KeyPair, String)} creates a * good certificate. */ @Test public void testCreateTlsSniCertificate() throws IOException, CertificateParsingException { String subject = "30c452b9bd088cdbc2c4094947025d7c.7364ea602ac325a1b55ceaae024fbe29.acme.invalid"; + + KeyPair keypair = KeyPairUtils.createKeyPair(2048); + + X509Certificate cert = CertificateUtils.createTlsSniCertificate(keypair, subject); + Date now = new Date(); Date end = new Date(now.getTime() + (8 * 24 * 60 * 60 * 1000L)); - X509Certificate cert = CertificateUtils.createTlsSniCertificate(subject); - assertThat(cert, not(nullValue())); assertThat(cert.getNotAfter(), is(greaterThan(now))); assertThat(cert.getNotAfter(), is(lessThan(end))); diff --git a/src/site/markdown/challenge/tls-sni.md b/src/site/markdown/challenge/tls-sni.md index 1980edd7..354555dd 100644 --- a/src/site/markdown/challenge/tls-sni.md +++ b/src/site/markdown/challenge/tls-sni.md @@ -1,6 +1,6 @@ # TLS-SNI -With the TLS-SNI challenge, you prove to the CA that you are able to control the web server of the domain to be authorized, by letting it respond to a SNI request with a self-signed cert. +With the TLS-SNI challenge, you prove to the CA that you are able to control the web server of the domain to be authorized, by letting it respond to a SNI request with a specific self-signed cert. After authorizing the challenge, `TlsSniChallenge` provides a subject: @@ -22,7 +22,20 @@ You need to create a self-signed certificate with the subject set as _Subject Al The `TlsSniChallenge` class does not generate a self-signed certificate, as it would require _Bouncy Castle_. However, there is a utility method in the _acme4j-utils_ module for this use case: ```java -X509Certificate cert = CertificateUtils.createTlsSniCertificate(String subject); +KeyPair sniKeyPair = KeyPairUtils.createKeyPair(2048); +X509Certificate cert = CertificateUtils.createTlsSniCertificate(sniKeyPair, subject); ``` +Now use `cert` and `sniKeyPair` to let your web server respond to a SNI request to `domain`. + The challenge is completed when the CA was able to send the SNI request and get the correct certificate in return. + +This shell command line may be helpful to test your web server configuration: + +```shell +echo QUIT | \ + openssl s_client -servername $domain -connect $server_ip:443 | \ + openssl x509 -text -noout +``` + +It should return a certificate with `domain` set as `X509v3 Subject Alternative Name`.