Jesse Wilson
Jesse Wilson

Reputation: 40593

Getting the trusted X509Certificate for a Java SSLSocket

I'm able to establish a TLS connection to https://google.com/. The remote service returns a chain of 3 certificates:

These certificates can be retrieved like so:

Certificate[] certificates = sslSocket.getSession().getPeerCertificates();

Unfortunately, this isn’t the complete chain. There’s a 4th certificate that’s installed in my local SSL context’s TrustManager. It looks like this:

Retrieving its name is straightforward:

String equifax = ((X509Certificate) peerCertificates[2]).getIssuerDN().getName();

What I want instead is the X509Certificate instance. How do I get the trusted CA cert that was used during a SSLSocket handshake?

Note that I’m using the system’s TrustManager by creating the SSL context like this:

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);

Upvotes: 2

Views: 4338

Answers (2)

Jesse Wilson
Jesse Wilson

Reputation: 40593

For perpetuity, I ended up getting the data I wanted with dirty reflection. I’m unable to control how the caller builds the SSL Context, as advised above.

Upvotes: 0

František Hartman
František Hartman

Reputation: 15086

You are almost there, just use the JVM default trust manager:

public static void main(String[] args) throws Exception{

    SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
    SSLSocket socket = (SSLSocket)factory.createSocket("www.google.com", 443);

    X509Certificate[] chain = socket.getSession().getPeerCertificateChain();

    String equifax = chain[2].getIssuerDN().getName();

    // JVM Default Trust Managers
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init((KeyStore) null);
    TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

    X509TrustManager manager = (X509TrustManager) trustManagers[0];

    for (java.security.cert.X509Certificate x509Certificate : manager.getAcceptedIssuers()) {
        if (equifax.equals(x509Certificate.getSubjectDN().getName())) {
            System.out.println(x509Certificate);
        }
    }

}

Upvotes: 3

Related Questions