SelfSignedCertificate configurable valid dates
Motivation: Users may want to control the valid dates for SelfSignedCertificate. Modifications: - Allow NOT_BEFORE and NOT_AFTER to be controlled via java system properties. Result: Fixes https://github.com/netty/netty/issues/3978
This commit is contained in:
parent
ed4928f62a
commit
c116c35ed0
@ -31,8 +31,9 @@ import java.security.PrivateKey;
|
||||
import java.security.Provider;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Date;
|
||||
|
||||
import static io.netty.handler.ssl.util.SelfSignedCertificate.*;
|
||||
import static io.netty.handler.ssl.util.SelfSignedCertificate.newSelfSignedCertificate;
|
||||
|
||||
/**
|
||||
* Generates a self-signed certificate using <a href="http://www.bouncycastle.org/">Bouncy Castle</a>.
|
||||
@ -41,13 +42,14 @@ final class BouncyCastleSelfSignedCertGenerator {
|
||||
|
||||
private static final Provider PROVIDER = new BouncyCastleProvider();
|
||||
|
||||
static String[] generate(String fqdn, KeyPair keypair, SecureRandom random) throws Exception {
|
||||
static String[] generate(String fqdn, KeyPair keypair, SecureRandom random, Date notBefore, Date notAfter)
|
||||
throws Exception {
|
||||
PrivateKey key = keypair.getPrivate();
|
||||
|
||||
// Prepare the information required for generating an X.509 certificate.
|
||||
X500Name owner = new X500Name("CN=" + fqdn);
|
||||
X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
|
||||
owner, new BigInteger(64, random), NOT_BEFORE, NOT_AFTER, owner, keypair.getPublic());
|
||||
owner, new BigInteger(64, random), notBefore, notAfter, owner, keypair.getPublic());
|
||||
|
||||
ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSAEncryption").build(key);
|
||||
X509CertificateHolder certHolder = builder.build(signer);
|
||||
|
@ -28,6 +28,7 @@ import sun.security.x509.X500Name;
|
||||
import sun.security.x509.X509CertImpl;
|
||||
import sun.security.x509.X509CertInfo;
|
||||
|
||||
import java.util.Date;
|
||||
import java.math.BigInteger;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PrivateKey;
|
||||
@ -41,7 +42,8 @@ import static io.netty.handler.ssl.util.SelfSignedCertificate.*;
|
||||
*/
|
||||
final class OpenJdkSelfSignedCertGenerator {
|
||||
|
||||
static String[] generate(String fqdn, KeyPair keypair, SecureRandom random) throws Exception {
|
||||
static String[] generate(String fqdn, KeyPair keypair, SecureRandom random, Date notBefore, Date notAfter)
|
||||
throws Exception {
|
||||
PrivateKey key = keypair.getPrivate();
|
||||
|
||||
// Prepare the information required for generating an X.509 certificate.
|
||||
@ -59,7 +61,7 @@ final class OpenJdkSelfSignedCertGenerator {
|
||||
} catch (CertificateException ignore) {
|
||||
info.set(X509CertInfo.ISSUER, owner);
|
||||
}
|
||||
info.set(X509CertInfo.VALIDITY, new CertificateValidity(NOT_BEFORE, NOT_AFTER));
|
||||
info.set(X509CertInfo.VALIDITY, new CertificateValidity(notBefore, notAfter));
|
||||
info.set(X509CertInfo.KEY, new CertificateX509Key(keypair.getPublic()));
|
||||
info.set(X509CertInfo.ALGORITHM_ID,
|
||||
new CertificateAlgorithmId(new AlgorithmId(AlgorithmId.sha1WithRSAEncryption_oid)));
|
||||
|
@ -19,6 +19,7 @@ package io.netty.handler.ssl.util;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.handler.codec.base64.Base64;
|
||||
import io.netty.util.CharsetUtil;
|
||||
import io.netty.util.internal.SystemPropertyUtil;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
@ -59,9 +60,11 @@ public final class SelfSignedCertificate {
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(SelfSignedCertificate.class);
|
||||
|
||||
/** Current time minus 1 year, just in case software clock goes back due to time synchronization */
|
||||
static final Date NOT_BEFORE = new Date(System.currentTimeMillis() - 86400000L * 365);
|
||||
private static final Date DEFAULT_NOT_BEFORE = new Date(SystemPropertyUtil.getLong(
|
||||
"io.netty.selfSignedCertificate.defaultNotBefore", System.currentTimeMillis() - 86400000L * 365));
|
||||
/** The maximum possible value in X.509 specification: 9999-12-31 23:59:59 */
|
||||
static final Date NOT_AFTER = new Date(253402300799000L);
|
||||
private static final Date DEFAULT_NOT_AFTER = new Date(SystemPropertyUtil.getLong(
|
||||
"io.netty.selfSignedCertificate.defaultNotAfter", 253402300799000L));
|
||||
|
||||
private final File certificate;
|
||||
private final File privateKey;
|
||||
@ -72,6 +75,15 @@ public final class SelfSignedCertificate {
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public SelfSignedCertificate() throws CertificateException {
|
||||
this(DEFAULT_NOT_BEFORE, DEFAULT_NOT_AFTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
* @param notBefore Certificate is not valid before this time
|
||||
* @param notAfter Certificate is not valid after this time
|
||||
*/
|
||||
public SelfSignedCertificate(Date notBefore, Date notAfter) throws CertificateException {
|
||||
this("example.com");
|
||||
}
|
||||
|
||||
@ -81,9 +93,20 @@ public final class SelfSignedCertificate {
|
||||
* @param fqdn a fully qualified domain name
|
||||
*/
|
||||
public SelfSignedCertificate(String fqdn) throws CertificateException {
|
||||
this(fqdn, DEFAULT_NOT_BEFORE, DEFAULT_NOT_AFTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param fqdn a fully qualified domain name
|
||||
* @param notBefore Certificate is not valid before this time
|
||||
* @param notAfter Certificate is not valid after this time
|
||||
*/
|
||||
public SelfSignedCertificate(String fqdn, Date notBefore, Date notAfter) throws CertificateException {
|
||||
// Bypass entrophy collection by using insecure random generator.
|
||||
// We just want to generate it without any delay because it's for testing purposes only.
|
||||
this(fqdn, ThreadLocalInsecureRandom.current(), 1024);
|
||||
this(fqdn, ThreadLocalInsecureRandom.current(), 1024, notBefore, notAfter);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,6 +117,20 @@ public final class SelfSignedCertificate {
|
||||
* @param bits the number of bits of the generated private key
|
||||
*/
|
||||
public SelfSignedCertificate(String fqdn, SecureRandom random, int bits) throws CertificateException {
|
||||
this(fqdn, random, bits, DEFAULT_NOT_BEFORE, DEFAULT_NOT_AFTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param fqdn a fully qualified domain name
|
||||
* @param random the {@link java.security.SecureRandom} to use
|
||||
* @param bits the number of bits of the generated private key
|
||||
* @param notBefore Certificate is not valid before this time
|
||||
* @param notAfter Certificate is not valid after this time
|
||||
*/
|
||||
public SelfSignedCertificate(String fqdn, SecureRandom random, int bits, Date notBefore, Date notAfter)
|
||||
throws CertificateException {
|
||||
// Generate an RSA key pair.
|
||||
final KeyPair keypair;
|
||||
try {
|
||||
@ -108,12 +145,12 @@ public final class SelfSignedCertificate {
|
||||
String[] paths;
|
||||
try {
|
||||
// Try the OpenJDK's proprietary implementation.
|
||||
paths = OpenJdkSelfSignedCertGenerator.generate(fqdn, keypair, random);
|
||||
paths = OpenJdkSelfSignedCertGenerator.generate(fqdn, keypair, random, notBefore, notAfter);
|
||||
} catch (Throwable t) {
|
||||
logger.debug("Failed to generate a self-signed X.509 certificate using sun.security.x509:", t);
|
||||
try {
|
||||
// Try Bouncy Castle if the current JVM didn't have sun.security.x509.
|
||||
paths = BouncyCastleSelfSignedCertGenerator.generate(fqdn, keypair, random);
|
||||
paths = BouncyCastleSelfSignedCertGenerator.generate(fqdn, keypair, random, notBefore, notAfter);
|
||||
} catch (Throwable t2) {
|
||||
logger.debug("Failed to generate a self-signed X.509 certificate using Bouncy Castle:", t2);
|
||||
throw new CertificateException(
|
||||
|
Loading…
Reference in New Issue
Block a user