23.4 Practical TLS Implementations and Patterns
This section covers real-world TLS implementations for HTTPS servers, clients, and advanced scenarios.
HTTPS Server with Custom SSL Configuration
// HTTPS Server Implementation
public class HTTPSServerImplementation {
// Basic HTTPS server using HttpServer
public static void createBasicHTTPSServer(int port, SSLContext sslContext)
throws Exception {
com.sun.net.httpserver.HttpServer server =
com.sun.net.httpserver.HttpServer.create(new java.net.InetSocketAddress(port), 0);
// Create HTTPS server
com.sun.net.httpserver.HttpsServer httpsServer =
com.sun.net.httpserver.HttpsServer.create(
new java.net.InetSocketAddress(port), 0);
// Configure SSL
httpsServer.setHttpsConfigurator(new com.sun.net.httpserver.HttpsConfigurator(sslContext) {
@Override
public void configure(com.sun.net.httpserver.HttpsParameters params) {
// Get SSL parameters from SSLContext
SSLContext context = getSSLContext();
SSLEngine engine = context.createSSLEngine();
// Configure parameters
SSLParameters sslParams = SSLParametersConfiguration.createStrictSSLParameters();
params.setSSLParameters(sslParams);
params.setNeedClientAuth(false);
}
});
// Add request handler
httpsServer.createContext("/", exchange -> {
String response = "Hello from HTTPS server!";
exchange.getResponseHeaders().set("Content-Type", "text/plain");
exchange.sendResponseHeaders(200, response.length());
exchange.getResponseBody().write(response.getBytes());
exchange.close();
});
httpsServer.setExecutor(java.util.concurrent.Executors.newFixedThreadPool(4));
httpsServer.start();
System.out.println("HTTPS Server started on port " + port);
}
// Complete HTTPS server example with configuration
public static void createConfiguredHTTPSServer(
int port,
String keyStorePath,
String keyStorePassword,
String keyPassword) throws Exception {
// Configure SSL context
SSLContext sslContext = SSLContextConfiguration.createSSLContextWithKeyStore(
keyStorePath, keyStorePassword, keyPassword);
// Create HTTPS server
com.sun.net.httpserver.HttpsServer httpsServer =
com.sun.net.httpserver.HttpsServer.create(
new java.net.InetSocketAddress(port), 0);
// Configure with strict SSL parameters
httpsServer.setHttpsConfigurator(new com.sun.net.httpserver.HttpsConfigurator(sslContext) {
@Override
public void configure(com.sun.net.httpserver.HttpsParameters params) {
try {
SSLContext context = getSSLContext();
SSLEngine engine = context.createSSLEngine();
// Strict configuration
SSLParameters sslParams = new SSLParameters();
sslParams.setProtocols(new String[]{"TLSv1.3", "TLSv1.2"});
sslParams.setCipherSuites(new String[]{
"TLS_AES_256_GCM_SHA384",
"TLS_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"
});
sslParams.setNeedClientAuth(false);
params.setSSLParameters(sslParams);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
// Add handlers
httpsServer.createContext("/api/health", exchange -> {
String response = "{\"status\": \"healthy\"}";
exchange.getResponseHeaders().set("Content-Type", "application/json");
exchange.sendResponseHeaders(200, response.length());
exchange.getResponseBody().write(response.getBytes());
exchange.close();
});
httpsServer.createContext("/api/data", exchange -> {
if ("GET".equals(exchange.getRequestMethod())) {
String response = "{\"data\": \"secured\"}";
exchange.getResponseHeaders().set("Content-Type", "application/json");
exchange.sendResponseHeaders(200, response.length());
exchange.getResponseBody().write(response.getBytes());
} else {
exchange.sendResponseHeaders(405, 0);
}
exchange.close();
});
httpsServer.setExecutor(java.util.concurrent.Executors.newFixedThreadPool(10));
httpsServer.start();
System.out.println("Configured HTTPS Server started on port " + port);
}
// Client authentication (mutual TLS)
public static void createMutualTLSServer(
int port,
String keyStorePath, String keyStorePassword, String keyPassword,
String trustStorePath, String trustStorePassword) throws Exception {
// Configure with both key and trust stores
SSLContext sslContext = SSLContextConfiguration.createCompleteSSLContext(
keyStorePath, keyStorePassword, keyPassword,
trustStorePath, trustStorePassword);
com.sun.net.httpserver.HttpsServer httpsServer =
com.sun.net.httpserver.HttpsServer.create(
new java.net.InetSocketAddress(port), 0);
// Configure mutual TLS
httpsServer.setHttpsConfigurator(new com.sun.net.httpserver.HttpsConfigurator(sslContext) {
@Override
public void configure(com.sun.net.httpserver.HttpsParameters params) {
SSLContext context = getSSLContext();
SSLEngine engine = context.createSSLEngine();
SSLParameters sslParams = SSLParametersConfiguration.createStrictSSLParameters();
sslParams.setNeedClientAuth(true); // Require client certificate
params.setSSLParameters(sslParams);
}
});
httpsServer.createContext("/secure", exchange -> {
try {
// Access client certificate if available
java.security.cert.X509Certificate[] clientCerts =
(java.security.cert.X509Certificate[])
exchange.getAttribute("javax.net.ssl.peer_certificates");
String clientInfo = "No client certificate";
if (clientCerts != null && clientCerts.length > 0) {
clientInfo = clientCerts[0].getSubjectDN().toString();
}
String response = "Authenticated client: " + clientInfo;
exchange.getResponseHeaders().set("Content-Type", "text/plain");
exchange.sendResponseHeaders(200, response.length());
exchange.getResponseBody().write(response.getBytes());
} catch (Exception e) {
exchange.sendResponseHeaders(500, 0);
}
exchange.close();
});
httpsServer.setExecutor(java.util.concurrent.Executors.newFixedThreadPool(10));
httpsServer.start();
System.out.println("Mutual TLS Server started on port " + port);
}
}
HTTPS Client Implementation
// HTTPS Client Patterns
public class HTTPSClientImplementation {
// Simple HTTPS GET request
public static String simpleHTTPSGet(String url) throws Exception {
HttpClient client = HTTPClientSSLConfiguration.createBasicHTTPSClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(java.net.URI.create(url))
.GET()
.timeout(java.time.Duration.ofSeconds(30))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
return response.body();
}
// HTTPS POST with custom SSL
public static String httpsPostWithCustomSSL(
String url,
String trustStorePath,
String trustStorePassword,
String jsonBody) throws Exception {
SSLContext sslContext = SSLContextConfiguration.createSSLContextWithTrustStore(
trustStorePath, trustStorePassword);
HttpClient client = HTTPClientSSLConfiguration.createCustomHTTPSClient(sslContext);
HttpRequest request = HttpRequest.newBuilder()
.uri(java.net.URI.create(url))
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.header("Content-Type", "application/json")
.timeout(java.time.Duration.ofSeconds(30))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
return response.body();
}
// Mutual TLS client
public static String mutualTLSRequest(
String url,
String keyStorePath,
String keyStorePassword,
String keyPassword,
String trustStorePath,
String trustStorePassword) throws Exception {
SSLContext sslContext = SSLContextConfiguration.createCompleteSSLContext(
keyStorePath, keyStorePassword, keyPassword,
trustStorePath, trustStorePassword);
HttpClient client = HTTPClientSSLConfiguration.createCustomHTTPSClient(sslContext);
HttpRequest request = HttpRequest.newBuilder()
.uri(java.net.URI.create(url))
.GET()
.timeout(java.time.Duration.ofSeconds(30))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println("Protocol: " + response.version());
System.out.println("Status: " + response.statusCode());
return response.body();
}
// Client with retry and circuit breaker
public static class ResilientHTTPSClient {
private final HttpClient client;
private final int maxRetries;
private final java.time.Duration retryDelay;
public ResilientHTTPSClient(HttpClient client, int maxRetries,
java.time.Duration retryDelay) {
this.client = client;
this.maxRetries = maxRetries;
this.retryDelay = retryDelay;
}
public String requestWithRetry(String url, HttpRequest.Builder requestBuilder)
throws Exception {
int attempts = 0;
while (attempts < maxRetries) {
try {
HttpRequest request = requestBuilder
.uri(java.net.URI.create(url))
.timeout(java.time.Duration.ofSeconds(10))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() >= 200 && response.statusCode() < 300) {
return response.body();
}
if (response.statusCode() >= 500) {
// Retry on server error
attempts++;
if (attempts < maxRetries) {
Thread.sleep(retryDelay.toMillis());
continue;
}
}
throw new Exception("HTTP " + response.statusCode());
} catch (java.net.ConnectException | java.net.SocketTimeoutException e) {
attempts++;
if (attempts >= maxRetries) {
throw e;
}
Thread.sleep(retryDelay.toMillis());
}
}
throw new Exception("Max retries exceeded");
}
}
}
SSL/TLS Socket Pair Communication
// Direct Socket Communication
public class SocketPairCommunication {
// Server using SSL sockets
public static void startSSLSocketServer(int port, SSLContext sslContext)
throws Exception {
javax.net.ServerSocketFactory factory = sslContext.getServerSocketFactory();
javax.net.ssl.SSLServerSocket serverSocket =
(javax.net.ssl.SSLServerSocket) factory.createServerSocket(port);
// Configure server socket
serverSocket.setEnabledProtocols(new String[]{"TLSv1.3", "TLSv1.2"});
System.out.println("SSL Socket server listening on port " + port);
// Accept and handle connections
java.util.concurrent.ExecutorService executor =
java.util.concurrent.Executors.newFixedThreadPool(10);
try {
while (true) {
javax.net.ssl.SSLSocket clientSocket =
(javax.net.ssl.SSLSocket) serverSocket.accept();
executor.submit(() -> handleSSLConnection(clientSocket));
}
} finally {
serverSocket.close();
}
}
// Handle individual SSL connection
private static void handleSSLConnection(javax.net.ssl.SSLSocket socket) {
try {
// Get connection information
javax.net.ssl.SSLSession session = socket.getSession();
System.out.println("Client connected: " + socket.getInetAddress());
System.out.println(" Protocol: " + session.getProtocol());
System.out.println(" Cipher: " + session.getCipherSuite());
// Read and echo data
java.io.BufferedReader reader = new java.io.BufferedReader(
new java.io.InputStreamReader(socket.getInputStream()));
java.io.PrintWriter writer = new java.io.PrintWriter(
socket.getOutputStream(), true);
String line;
while ((line = reader.readLine()) != null) {
System.out.println("Received: " + line);
writer.println("Echo: " + line);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// Client using SSL sockets
public static String connectWithSSLSocket(String host, int port, String message,
SSLContext sslContext) throws Exception {
javax.net.SocketFactory factory = sslContext.getSocketFactory();
javax.net.ssl.SSLSocket socket =
(javax.net.ssl.SSLSocket) factory.createSocket(host, port);
try {
// Initiate handshake
socket.startHandshake();
// Get connection info
javax.net.ssl.SSLSession session = socket.getSession();
System.out.println("Connected to " + host + ":" + port);
System.out.println(" Protocol: " + session.getProtocol());
System.out.println(" Cipher: " + session.getCipherSuite());
// Send message
java.io.PrintWriter writer = new java.io.PrintWriter(
socket.getOutputStream(), true);
writer.println(message);
// Read response
java.io.BufferedReader reader = new java.io.BufferedReader(
new java.io.InputStreamReader(socket.getInputStream()));
String response = reader.readLine();
return response;
} finally {
socket.close();
}
}
}
Advanced TLS Patterns
// Advanced TLS Implementation Patterns
public class AdvancedTLSPatterns {
// TLS with proxy/load balancer
public static class ProxyAwareHTTPClient {
private final HttpClient client;
private final String proxyHost;
private final int proxyPort;
public ProxyAwareHTTPClient(HttpClient client, String proxyHost, int proxyPort) {
this.client = client;
this.proxyHost = proxyHost;
this.proxyPort = proxyPort;
}
public String requestThroughProxy(String url) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(java.net.URI.create(url))
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
return response.body();
}
}
// Certificate pinning with backup pins
public static class CertificatePinningStrategy {
private final String primaryPin;
private final String backupPin;
public CertificatePinningStrategy(String primaryPin, String backupPin) {
this.primaryPin = primaryPin;
this.backupPin = backupPin;
}
public void validateCertificate(java.security.cert.X509Certificate cert)
throws Exception {
try {
String actualPin = CertificatePinning.PublicKeyPinning
.getPinnedKeyHash(cert);
if (primaryPin.equals(actualPin)) {
System.out.println("Primary pin matched");
return;
}
if (backupPin.equals(actualPin)) {
System.out.println("Backup pin matched");
return;
}
throw new java.security.cert.CertificateException(
"No matching certificate pin");
} catch (Exception e) {
throw new java.security.cert.CertificateException(
"Pin validation failed", e);
}
}
}
// Session resumption for performance
public static class SessionResumingClient {
private final HttpClient client;
private final java.util.Map<String, byte[]> sessionCache;
public SessionResumingClient(HttpClient client) {
this.client = client;
this.sessionCache = new java.util.concurrent.ConcurrentHashMap<>();
}
public String request(String url) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(java.net.URI.create(url))
.GET()
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
// Could cache session information for reuse
// Actual session resumption handled by SSLEngine
return response.body();
}
}
// Monitoring and metrics
public static class TLSMetrics {
private int successfulHandshakes;
private int failedHandshakes;
private long totalHandshakeTime;
public synchronized void recordSuccessfulHandshake(long durationMillis) {
successfulHandshakes++;
totalHandshakeTime += durationMillis;
}
public synchronized void recordFailedHandshake() {
failedHandshakes++;
}
public synchronized void printMetrics() {
System.out.println("=== TLS METRICS ===");
System.out.println("Successful handshakes: " + successfulHandshakes);
System.out.println("Failed handshakes: " + failedHandshakes);
if (successfulHandshakes > 0) {
System.out.println("Average handshake time: " +
(totalHandshakeTime / successfulHandshakes) + "ms");
}
}
}
// Gradual cipher suite upgrade
public static class CipherSuiteUpgradeStrategy {
private final String[] legacyCipherSuites;
private final String[] modernCipherSuites;
private volatile String[] activeCipherSuites;
public CipherSuiteUpgradeStrategy() {
this.legacyCipherSuites = SSLParametersConfiguration.CipherSuiteLevels
.getMaximumCompatibilityCipherSuites();
this.modernCipherSuites = SSLParametersConfiguration.CipherSuiteLevels
.getModernCipherSuites();
this.activeCipherSuites = legacyCipherSuites;
}
public String[] getActiveCipherSuites() {
return activeCipherSuites;
}
public void upgradeToModernCipherSuites() {
System.out.println("Upgrading to modern cipher suites");
this.activeCipherSuites = modernCipherSuites;
}
public void rollbackToLegacyCipherSuites() {
System.out.println("Rolling back to legacy cipher suites");
this.activeCipherSuites = legacyCipherSuites;
}
}
}
Testing and Verification
// TLS Testing and Verification
public class TLSTestingAndVerification {
// Verify TLS connection
public static void verifyTLSConnection(String host, int port) throws Exception {
SSLContext context = SSLContextConfiguration.createDefaultSSLContext();
javax.net.SocketFactory factory = context.getSocketFactory();
javax.net.ssl.SSLSocket socket =
(javax.net.ssl.SSLSocket) factory.createSocket(host, port);
try {
socket.startHandshake();
javax.net.ssl.SSLSession session = socket.getSession();
System.out.println("=== TLS VERIFICATION RESULT ===");
System.out.println("Host: " + host + ":" + port);
System.out.println("Protocol: " + session.getProtocol());
System.out.println("Cipher: " + session.getCipherSuite());
System.out.println("Session ID: " +
java.util.HexFormat.of().formatHex(session.getId()));
java.security.cert.Certificate[] certs = socket.getSession()
.getPeerCertificates();
if (certs.length > 0) {
java.security.cert.X509Certificate cert =
(java.security.cert.X509Certificate) certs[0];
System.out.println("Certificate Subject: " + cert.getSubjectDN());
System.out.println("Certificate Issuer: " + cert.getIssuerDN());
}
} finally {
socket.close();
}
}
// Test cipher suite support
public static void testCipherSuiteSupport() throws Exception {
SSLContext context = SSLContext.getInstance("TLSv1.3");
context.init(null, null, new java.security.SecureRandom());
SSLEngine engine = context.createSSLEngine();
System.out.println("=== CIPHER SUITE SUPPORT TEST ===");
String[] testSuites = {
"TLS_AES_256_GCM_SHA384",
"TLS_AES_128_GCM_SHA256",
"TLS_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
};
java.util.Set<String> supported =
java.util.Set.of(engine.getSupportedCipherSuites());
for (String suite : testSuites) {
System.out.println(suite + ": " +
(supported.contains(suite) ? "SUPPORTED" : "NOT SUPPORTED"));
}
}
}
Best Practices for Production
- Use TLS 1.3 by default: Falls back to 1.2 for older clients.
- Keep certificates updated: Monitor expiration dates and renewal.
- Implement certificate pinning: For critical API connections.
- Enable OCSP stapling: For efficient revocation checking.
- Monitor handshake failures: Log and alert on SSL errors.
- Rotate certificates gracefully: Plan certificate renewal without downtime.
- Test TLS configuration: Use online tools and penetration testing.
- Document cipher suite choices: Explain why specific suites selected.
- Implement retry logic: Handle transient TLS failures gracefully.
- Secure private keys: Use HSM or secure key management in production.