Make CertificateUtils.createTlsSniCertificate more useful for TLS-SNI challenge

pull/17/merge
Richard Körber 2015-12-26 12:40:37 +01:00
parent 5e699df6c1
commit 7b6af21cd1
3 changed files with 25 additions and 9 deletions

View File

@ -95,19 +95,18 @@ public final class CertificateUtils {
* Creates a self-signed {@link X509Certificate} that can be used for * Creates a self-signed {@link X509Certificate} that can be used for
* {@link TlsSniChallenge}. The certificate is valid for 7 days. * {@link TlsSniChallenge}. The certificate is valid for 7 days.
* *
* @param keypair
* A domain {@link KeyPair} to be used for the challenge
* @param subject * @param subject
* Subject to create a certificate for * Subject to create a certificate for
* @return Created certificate * @return Created certificate
*/ */
public static X509Certificate createTlsSniCertificate(String subject) throws IOException { public static X509Certificate createTlsSniCertificate(KeyPair keypair, String subject) throws IOException {
final int certSize = 2048;
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
final long validSpanMs = 7 * 24 * 60 * 60 * 1000L; final long validSpanMs = 7 * 24 * 60 * 60 * 1000L;
final String signatureAlg = "SHA256withRSA"; final String signatureAlg = "SHA256withRSA";
try { try {
KeyPair keypair = KeyPairUtils.createKeyPair(certSize);
X500Name issuer = new X500Name("CN=acme.invalid"); X500Name issuer = new X500Name("CN=acme.invalid");
BigInteger serial = BigInteger.valueOf(now); BigInteger serial = BigInteger.valueOf(now);
Date notBefore = new Date(now); Date notBefore = new Date(now);

View File

@ -20,6 +20,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.KeyPair;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.security.cert.CertificateParsingException; 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. * good certificate.
*/ */
@Test @Test
public void testCreateTlsSniCertificate() throws IOException, CertificateParsingException { public void testCreateTlsSniCertificate() throws IOException, CertificateParsingException {
String subject = "30c452b9bd088cdbc2c4094947025d7c.7364ea602ac325a1b55ceaae024fbe29.acme.invalid"; String subject = "30c452b9bd088cdbc2c4094947025d7c.7364ea602ac325a1b55ceaae024fbe29.acme.invalid";
KeyPair keypair = KeyPairUtils.createKeyPair(2048);
X509Certificate cert = CertificateUtils.createTlsSniCertificate(keypair, subject);
Date now = new Date(); Date now = new Date();
Date end = new Date(now.getTime() + (8 * 24 * 60 * 60 * 1000L)); Date end = new Date(now.getTime() + (8 * 24 * 60 * 60 * 1000L));
X509Certificate cert = CertificateUtils.createTlsSniCertificate(subject);
assertThat(cert, not(nullValue())); assertThat(cert, not(nullValue()));
assertThat(cert.getNotAfter(), is(greaterThan(now))); assertThat(cert.getNotAfter(), is(greaterThan(now)));
assertThat(cert.getNotAfter(), is(lessThan(end))); assertThat(cert.getNotAfter(), is(lessThan(end)));

View File

@ -1,6 +1,6 @@
# TLS-SNI # 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: 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: 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 ```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. 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`.