Simple Java HTTPS server
What I eventually used was this:
try {
// Set up the socket address
InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(), config.getHttpsPort());
// Initialise the HTTPS server
HttpsServer httpsServer = HttpsServer.create(address, 0);
SSLContext sslContext = SSLContext.getInstance("TLS");
// Initialise the keystore
char[] password = "simulator".toCharArray();
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream fis = new FileInputStream("lig.keystore");
ks.load(fis, password);
// Set up the key manager factory
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, password);
// Set up the trust manager factory
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ks);
// Set up the HTTPS context and parameters
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext) {
public void configure(HttpsParameters params) {
try {
// Initialise the SSL context
SSLContext c = SSLContext.getDefault();
SSLEngine engine = c.createSSLEngine();
params.setNeedClientAuth(false);
params.setCipherSuites(engine.getEnabledCipherSuites());
params.setProtocols(engine.getEnabledProtocols());
// Get the default parameters
SSLParameters defaultSSLParameters = c.getDefaultSSLParameters();
params.setSSLParameters(defaultSSLParameters);
} catch (Exception ex) {
ILogger log = new LoggerFactory().getLogger();
log.exception(ex);
log.error("Failed to create HTTPS port");
}
}
});
LigServer server = new LigServer(httpsServer);
joinableThreadList.add(server.getJoinableThread());
} catch (Exception exception) {
log.exception(exception);
log.error("Failed to create HTTPS server on port " + config.getHttpsPort() + " of localhost");
}
To generate a keystore:
$ keytool -genkeypair -keyalg RSA -alias self_signed -keypass simulator \
-keystore lig.keystore -storepass simulator
See also here.
Potentially storepass and keypass might be different, in which case the ks.load
and kmf.init
must use storepass and keypass, respectively.
Java https server
I have been able to get the program working with SSL with the code I provided in my question. I believe the issue I was having was because of the keystore I had generated. Using this command to generate the keystore it worked:
keytool -genkey -alias alias -keyalg RSA -keystore keystore.jks -keysize 2048
Java HTTPS Server: Mutual SSL Authentication
After very long searching I noticed that the configure(..)
method of the HttpsConfigurator
is wrong. I didn't set the SSLParameters
correctly!
It should look like this:
@Override
public void configure(final HttpsParameters params)
{
try
{
final SSLParameters sslParams = getSSLContext().getDefaultSSLParameters();
final SSLEngine sslEngine = getSSLContext().createSSLEngine();
sslParams.setNeedClientAuth( true );
sslParams.setCipherSuites( sslEngine.getEnabledCipherSuites() );
sslParams.setProtocols( sslEngine.getEnabledProtocols() );
params.setSSLParameters( sslParams );
}
catch ( final Exception e )
{
LOG.error( ExceptionUtils.getStackTrace( e ) );
}
}
Why doesn't this Java HttpsServer successfully complete a TLS handshake?
Here's what ended up working:
X509Certificate leafCert = new JcaX509CertificateConverter()
.getCertificate(new JcaX509v3CertificateBuilder(
rootStore.getCertificate("signingcert"),
/* serial= */ BigInteger.valueOf(now.toEpochMilli()),
/* notBefore= */ Date
.from(now.minus(Duration.ofMinutes(5))),
/* notAfter= */ Date.from(now.plus(Duration.ofDays(1))),
new X500Name(new RDN[0]), leafPair.getPublic())
.addExtension(Extension.subjectAlternativeName,
/* isCritical= */ true,
new GeneralNames(new GeneralName(
GeneralName.dNSName,
"localhost")))
.addExtension(Extension.extendedKeyUsage,
/* isCritical= */ false,
new ExtendedKeyUsage(
KeyPurposeId.id_kp_serverAuth))
.build(new JcaContentSignerBuilder(
"SHA256withRSA").build(
(PrivateKey) rootStore.getKey(
"signingcertprivkey",
"password"
.toCharArray()))));
How to add the intermediate certificate within Java HTTPSServer
I solved it by appending the intermediate certificate to my certificate in the keystore explorer. Thanks to Robert.
Related Topics
Create Simple Pojo Classes (Bytecode) at Runtime (Dynamically)
How to Use a Variable of One Method in Another Method
Create Bar Chart in Excel with Apache Poi
How to Take Screenshots Fast in Java
Gwt: Timer and Scheduler Classes
How to Represent a Range in Java
How to Check the Type of a Value from a JSONobject
Why Is the Tostring() Method Being Called When I Print an Object
Value Change Listener for Javafx's Textfield
Why Can't You Reduce the Visibility of a Method in a Java Subclass
Efficiently Finding the Intersection of a Variable Number of Sets of Strings
Error:Java.Lang.Nosuchmethoderror: Org.Objectweb.Asm.Classwriter.<Init>(I)V
Why Is Constructor of Super Class Invoked When We Declare the Object of Sub Class? (Java)
How Can a Keylistener Detect Key Combinations (E.G., Alt + 1 + 1)
How to Programmatically Inject a Java Cdi Managed Bean into a Local Variable in a (Static) Method
Spring Security's Securitycontextholder: Session or Request Bound