All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.dona.doip.util.tls.TlsProtocolAndCipherSuiteConfigurationUtil Maven / Gradle / Ivy

package net.dona.doip.util.tls;

import javax.net.ssl.*;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

/**
 * Utilities for restricting TLS connections to use appropriate protocol versions and cipher suites.
 */
public class TlsProtocolAndCipherSuiteConfigurationUtil {

    /**
     * A list of TLS protocols both provided by the JVM and considered sufficiently strong.
     */
    public static final String[] ENABLED_PROTOCOLS;

    /**
     * A list of TLS cipher suites both provided by the JVM and considered sufficiently strong.
     */
    public static final String[] ENABLED_CIPHER_SUITES;

    // prefer GCM to CBC; SHA2 to SHA1; ECDHE to DHE; AES256 to AES128
    private static final String[] DESIRED_CIPHER_SUITES = {
            "TLS_AES_256_GCM_SHA384", // TLS 1.3
            "TLS_AES_128_GCM_SHA256", // TLS 1.3
            "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
            "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
            "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
            "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
            "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
            "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
            "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
            "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
            "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
            "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
            "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
            "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
            "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
            "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
            "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
            "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
    };

    static {
        SSLContext context = getAllTrustingClientSSLContext();
        String[] supportedCipherSuitesArray = context.getSupportedSSLParameters().getCipherSuites();
        List supportedCipherSuites = java.util.Arrays.asList(supportedCipherSuitesArray);
        List enabledCipherSuites = new ArrayList<>(java.util.Arrays.asList(DESIRED_CIPHER_SUITES));
        enabledCipherSuites.retainAll(supportedCipherSuites);
        ENABLED_CIPHER_SUITES = enabledCipherSuites.toArray(new String[0]);
    }

    static {
        SSLContext context = getAllTrustingClientSSLContext();
        String[] supportedProtocols = context.getSupportedSSLParameters().getProtocols();
        List enabledProtocols = new ArrayList<>();
        for (String protocol : supportedProtocols) {
            if (protocol.startsWith("SSL")) continue;
            if ("TLSv1.2".compareTo(protocol) > 0) continue;
            enabledProtocols.add(protocol);
        }
        ENABLED_PROTOCOLS = enabledProtocols.toArray(new String[0]);
    }

    /**
     * Configures an {@code SSLSocket} to use the appropriate protocols and cipher suites.
     * If the input is not an {@code SSLSocket} no action is taken.
     *
     * @param s a {@code Socket}
     * @return the input {@code Socket}
     */
    public static Socket configureEnabledProtocolsAndCipherSuites(Socket s) {
        if (s instanceof SSLSocket) {
            ((SSLSocket) s).setEnabledProtocols(TlsProtocolAndCipherSuiteConfigurationUtil.ENABLED_PROTOCOLS);
            ((SSLSocket) s).setEnabledCipherSuites(TlsProtocolAndCipherSuiteConfigurationUtil.ENABLED_CIPHER_SUITES);
        }
        return s;
    }

    /**
     * Configures an {@code SSLServerSocket} to use the appropriate protocols and cipher suites.
     * If the input is not an {@code SSLServerSocket} no action is taken.
     *
     * @param s a {@code ServerSocket}
     * @return the input {@code ServerSocket}
     */
    public static ServerSocket configureEnabledProtocolsAndCipherSuites(ServerSocket s) {
        if (s instanceof SSLServerSocket) {
            ((SSLServerSocket) s).setEnabledProtocols(TlsProtocolAndCipherSuiteConfigurationUtil.ENABLED_PROTOCOLS);
            ((SSLServerSocket) s).setEnabledCipherSuites(TlsProtocolAndCipherSuiteConfigurationUtil.ENABLED_CIPHER_SUITES);
        }
        return s;
    }

    /**
     * Returns an {@code SSLContext} which trusts all server certificates.
     *
     * @return an {@code SSLContext} which trusts all server certificates
     */
    public static SSLContext getAllTrustingClientSSLContext() {
        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            TrustManager[] tm = new TrustManager[] { new AllTrustingTrustManager() };
            sslContext.init(null, tm, null);
            return sslContext;
        } catch (NoSuchAlgorithmException e) {
            throw new AssertionError(e);
        } catch (KeyManagementException e) {
            throw new AssertionError(e);
        }
    }

    /**
     * A wrapper for an {@code SSLSocketFactory} which ensures that
     * all created sockets will use appropriate protocols and cipher suites.
     */
    public static class SocketFactoryWrapper extends SSLSocketFactory {
        private final SSLSocketFactory delegate;

        public SocketFactoryWrapper(SSLSocketFactory delegate) {
            this.delegate = delegate;
        }

        @Override
        public Socket createSocket() throws IOException {
            return configureEnabledProtocolsAndCipherSuites(delegate.createSocket());
        }

        @Override
        public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
            return configureEnabledProtocolsAndCipherSuites(delegate.createSocket(address, port, localAddress, localPort));
        }

        @Override
        public Socket createSocket(InetAddress host, int port) throws IOException {
            return configureEnabledProtocolsAndCipherSuites(delegate.createSocket(host, port));
        }

        @Override
        public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
            return configureEnabledProtocolsAndCipherSuites(delegate.createSocket(s, host, port, autoClose));
        }

        @Override
        public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
            return configureEnabledProtocolsAndCipherSuites(delegate.createSocket(host, port, localHost, localPort));
        }

        @Override
        public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
            return configureEnabledProtocolsAndCipherSuites(delegate.createSocket(host, port));
        }

        @Override
        public String[] getDefaultCipherSuites() {
            return delegate.getDefaultCipherSuites();
        }

        @Override
        public String[] getSupportedCipherSuites() {
            return delegate.getSupportedCipherSuites();
        }

        @Override
        public boolean equals(Object obj) {
            return delegate.equals(obj);
        }

        @Override
        public int hashCode() {
            return delegate.hashCode();
        }

        @Override
        public String toString() {
            return delegate.toString();
        }
    }

    /**
     * A wrapper for an {@code SSLServerSocketFactory} which ensures that
     * all created server sockets will use appropriate protocols and cipher suites.
     */
    public static class ServerSocketFactoryWrapper extends SSLServerSocketFactory {
        private final SSLServerSocketFactory delegate;

        public ServerSocketFactoryWrapper(SSLServerSocketFactory delegate) {
            this.delegate = delegate;
        }

        @Override
        public ServerSocket createServerSocket() throws IOException {
            return configureEnabledProtocolsAndCipherSuites(delegate.createServerSocket());
        }

        @Override
        public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException {
            return delegate.createServerSocket(port, backlog, ifAddress);
        }

        @Override
        public ServerSocket createServerSocket(int port, int backlog) throws IOException {
            return delegate.createServerSocket(port, backlog);
        }

        @Override
        public ServerSocket createServerSocket(int port) throws IOException {
            return delegate.createServerSocket(port);
        }

        @Override
        public boolean equals(Object obj) {
            return delegate.equals(obj);
        }

        @Override
        public String[] getDefaultCipherSuites() {
            return delegate.getDefaultCipherSuites();
        }

        @Override
        public String[] getSupportedCipherSuites() {
            return delegate.getSupportedCipherSuites();
        }

        @Override
        public int hashCode() {
            return delegate.hashCode();
        }

        @Override
        public String toString() {
            return delegate.toString();
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy