Reputation: 40593
I'm able to establish a TLS connection to https://google.com/. The remote service returns a chain of 3 certificates:
CN=www.google.com, O=Google Inc, L=Mountain View, ST=California, C=US
CN=Google Internet Authority G2, O=Google Inc, C=US
CN=GeoTrust Global CA, O=GeoTrust Inc., C=US
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:
OU=Equifax Secure Certificate Authority, O=Equifax, C=US
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
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
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