TLS on apache server

I want to start Apache HTTP server in Java.

After a while I found this answer. And did as indicated there.

The KeyStore was created according to this instruction.

My code now:

import me.project.Main;
import org.apache.http.ExceptionLogger;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.bootstrap.HttpServer;
import org.apache.http.impl.bootstrap.ServerBootstrap;
import org.apache.http.ssl.SSLContexts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

public class Server {
    private static final Logger logger = LoggerFactory.getLogger(Server.class);
    private static HttpServer server;

    public static void createAndStart() {
        if (server != null) return;

        SSLContext sslContext = prepareSSLContext();
        SocketConfig config = SocketConfig.custom().setSoTimeout(1500).setTcpNoDelay(true).build();
        server = ServerBootstrap.bootstrap()
                .setListenerPort(43286)
                .setServerInfo("Test")
                .setSocketConfig(config)
                .setSslContext(sslContext)
                .setExceptionLogger(ExceptionLogger.STD_ERR)
                .registerHandler("/", new HelloPage())
                .create();
        System.out.println("Ok");
        try {
            server.start();
        } catch (IOException ioException) {
            logger.error("Cannot start server: ", ioException);
        }
    }

    private static SSLContext prepareSSLContext() {
        URL keyStoreFile = Main.class.getClassLoader().getResource("keystore.jks");
        if (keyStoreFile == null) {
            logger.error("Key store not found");
            System.exit(1);
        }

        SSLContext sslContext = null;
        try {
            sslContext = SSLContexts.custom()
                    .loadKeyMaterial(keyStoreFile, "mysuperpass".toCharArray(), "mysuperpass".toCharArray()).build();
        } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException | CertificateException | IOException e) {
            logger.error("Cannot init ssl context", e);
        }

        return sslContext;
    }
}

It starts sucessfully and prints “Ok”.

But a few things I still don’t understand:

  • It seems to me that this is still SSL protocol, not TLS
  • How can I make sure that the server really communicates using the encrypted TLS protocol (except to intercept traffic and watch)
  • How does the loadKeyMaterial (keyStore, storePass, KeyPass) method know which key to take from the store without the key alias?

I found another example of enabling TLS here, but I don’t understand where to use the object conn after:

DefaultBHttpClientConnection conn = new DefaultBHttpClientConnection(8 * 1204);
conn.bind(socket);

Sorry, I don’t know English well and translated this with Google Translate

Answer

It seems to me that this is still SSL protocol, not TLS

The classes were originally implemented for SSL(v3) in the 1990s, but they have implemented TLS since about 2000 (first 1.0, later 1.1 1.2 and now 1.3) while the names have remained the same for compatibility. In fact since 8u31 in 2014 SSLv3 has been disabled by default in the JVM configuration because it was broken by the “POODLE” attack and the ‘SSL’ classes in fact provide only TLS.

How can I make sure that the server really communicates using the encrypted TLS protocol (except to intercept traffic and watch)

Try connecting to it with TLS and non-TLS tools.

How does the loadKeyMaterial (keyStore, storePass, KeyPass) method know which key to take from the store without the key alias?

It uses the JSSE-default KeyManager which implements chooseServerAlias to return the first key-and-cert entry (i.e. PrivateKeyEntry) it finds that is suitable for a client-enabled ciphersuite — or for TLS 1.3 where this is no longer in the ciphersuite, a client-enabled sigalg. IIRC ‘first’ is in a hashmap-defined order which means for practical/human purposes it is arbitrary. But most servers use a keystore that contains only one PrivateKeyEntry so all choice sequences are the same.

Leave a Reply

Your email address will not be published. Required fields are marked *