It’s not quite black magic…

Problem: I need to connect to an SSL socket while ignoring the trust certificate chain, so I can connect to a self-signed SSL connection. In particular I want to connect to an LDAP server using the Netscape LDAP library but I keep hitting the error:

“Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target”

I managed to find a snippet of code with the correct solution here, and am basically repeating it here for my own edification.

First, to create a client socket you need to use a socket factory. But in order to connect to an SSL socket while bypassing the trust chain on the certificate, you must first set up the socket factory:

SocketFactory gSocketFactory;
...
SSLContext sc = SSLContext.getInstance("SSL");
TrustManager[] trustAll = new TrustManager[] {
        new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] arg0,
                    String arg1) throws CertificateException
                    {
                    }

            @Override
            public void checkServerTrusted(X509Certificate[] arg0,
                    String arg1) throws CertificateException
                    {
                    }

            @Override
            public X509Certificate[] getAcceptedIssuers()
            {
                return null;
            }
        }
};

sc.init(null, trustAll, new SecureRandom());
gSocketFactory = sc.getSocketFactory();

Once the socket factory has been created, you can make an SSL connection:

Socket socket = gSocketFactory.createSocket();
socket.connect(new InetSocketAddress(host,port));
// Do stuff with the socket

The magic bit of code creates a new trust management chain and installs it into a new SSLContext object, used to build our socket factory. The trusted chain contains one X509TrustManager, which does–nothing. And thus, we can connect to all SSL sockets without worrying if we have the correct certificate installed or if the remote SSL connection is properly signed.

Usual caviats remain: don’t do this unless you must, it creates all sorts of security problems (such as increased susceptibility to man in the middle attacks), your mileage may vary, limited supplies are available, no shoes no shirt no service.

One thought on “It’s not quite black magic…

  1. Hello I find your blog really good especially A comment left on Slashdot.
    I thought I will just add some information as you say this X509TrustManager does nothing.
    If you want to use self signed certificates in your client-side application you should create a BKS keystore using keytool + BC provider (https://bouncycastle.org/latest_releases.html) then store your root certificate in the keystore then add it to your SSLContext before creating a SSLSocketFactory.

    Ex.

    public SSLSocketFactory createSSLSocketFactory(final InputStream bksStoreStream, final String password) throws Exception {
    final KeyStore keyStore = KeyStore.getInstance(“BKS”);
    keyStore.load(bksStoreStream, password.toCharArray());

    final TrustManagerFactory x509Factory = TrustManagerFactory.getInstance(“X509”);
    x509Factory.init(keyStore);

    final SSLContext sslContext = SSLContext.getInstance(“TLSv1.2”);
    sslContext.init(null, x509Factory.getTrustManagers(), null);
    return sslContext.getSocketFactory();
    }

    Like

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s