简体   繁体   English

获取Java SSLSocket的受信任的X509证书

[英]Getting the trusted X509Certificate for a Java SSLSocket

I'm able to establish a TLS connection to https://google.com/ . 我可以建立到https://google.com/的TLS连接。 The remote service returns a chain of 3 certificates: 远程服务返回由3个证书组成的链:

  • 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. 我的本地SSL上下文的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. 我想要的是X509Certificate实例。 How do I get the trusted CA cert that was used during a SSLSocket handshake? 如何获得在SSLSocket握手期间使用的受信任CA证书?

Note that I'm using the system's TrustManager by creating the SSL context like this: 请注意,我通过创建SSL上下文来使用系统的TrustManager

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

You are almost there, just use the JVM default trust manager: 您快到了,只需使用JVM默认信任管理器:

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);
        }
    }

}

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. 如上所述,我无法控制调用方如何构建SSL上下文。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM