使用Java在运行时加载CA根证书 [英] Load CA root certificate at runtime in Java

查看:714
本文介绍了使用Java在运行时加载CA根证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

tl; dr:使用自定义CA而不将其添加到持久性密钥库。

我正在编写一个应该连接到a的Java应用程序使用HTTPS的远程服务器。连接的代码已准备就绪,但服务器的SSL证书是由 StartSSL 签署的,而不是在Java的CA根证书库中。

I am writing a Java application that should connect to a remote server using HTTPS. The code for the connection is ready, however the SSL certificate of the server was signed by StartSSL, which is not in Java's CA root cert store.

使用此代码,我从 https://www.google.com/ 这样的网站获取有效的证书信息:

Using this code, I get valid certificate information from websites like https://www.google.com/:

Response Code : 200
Cipher Suite : TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

Cert Type : X.509
Cert Hash Code : -1643391404
Cert Public Key Algorithm : RSA
Cert Public Key Format : X.509

Cert Type : X.509
Cert Hash Code : 771393018
Cert Public Key Algorithm : RSA
Cert Public Key Format : X.509

Cert Type : X.509
Cert Hash Code : 349192256
Cert Public Key Algorithm : RSA
Cert Public Key Format : X.509

相同的代码会抛出 SSLHandshakeException 我的域名(让我们称之为 https://www.example.com/ )。

The same code throws a SSLHandshakeException for my domain (let's call it https://www.example.com/).

当然我可以使用 keytool 手动将证书添加到密钥库(甚至可以使用 Runtime.exec(keytool ...) ),但这是肮脏的方式。我现在计划的是将StartSSL根证书添加到我的应用程序文件中以进行分发,然后在运行时将其加载到某个临时密钥库中。这样真正的密钥库保持不变。

Of course I could manually add the certificate to the keystore using keytool (maybe even with Runtime.exec("keytool ...")), but this is way to dirty. What I am planning now is to add the StartSSL root certificate to my application files for distribution and then loading it into some temporary keystore at runtime. This way the "real" keystore remains untouched.

从我读过的内容这里这里,我将不得不搞乱一些类,如 TrustManager 。我甚至找到了一种方法来完全关闭验证,但这不是我想要的,因为它似乎消除了加密通信的全部目的。

From what I have read here and here, I will have to mess with some classes like TrustManager. I even found a way to completely turn off the validation, but this is not what I want since it seems to eliminate the whole purpose of encrypted communication.

我甚至发现了一些行代码似乎完全符合我的要求,但我无法弄清楚如何调用此方法,即将哪些值作为参数传递:

I even found some lines of code that seem to do exactly what I want, but I cannot figure out how to call this method i.e. which values to pass as arguments:

public class SSLClasspathTrustStoreLoader {
    public static void setTrustStore(String trustStore, String password) throws Exception {
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509");
        KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
        InputStream keystoreStream = SSLClasspathTrustStoreLoader.class.getResourceAsStream(trustStore);
        keystore.load(keystoreStream, password.toCharArray());
        trustManagerFactory.init(keystore);
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustManagers, null);
        SSLContext.setDefault(sc);
    }
}

以前是否有人遇到类似情况?我将不胜感激任何有关如何处理此问题的建议。如果你甚至可以帮助我运行上面的代码,我会非常高兴!

Has anyone been in a similar situation before? I will appreciate any advice on how to handle this problem. If you could even help me to get the above code running, I'd be really happy!

推荐答案

你需要创建您已经找到的自定义TrustStore。
除此之外,您还需要创建一个自定义SSL套接字工厂,它使用您提到的自定义信任管理器,并将其注册到您正在使用的HTTP框架。详细信息实际上取决于您选择的框架。

You will need to create a custom TrustStore as you already found. In addition to this, you will need to create a custom SSL socket factory which uses the custom trust manger you mentioned, and register it with the HTTP framework you are using. Details really depends on the framework of your choice.

使用 keytool 实用程序将证书添加到默认密钥存储区没有任何问题。您可能会发现需要多个证书。如果是这种情况,您必须确保整个Java应用程序使用相同的密钥存储区作为单一事实来源。如果在同一个应用程序中使用多个密钥库,它可能会变得非常毛茸茸。

Nothing wrong with adding a certificate to a default key store using keytool utility. You might find there are more than a single certificate is needed. If this is a case, you have to make sure whole Java application is using the same key store as a single source of truth. It might get very hairy if you use multiple key stores within the same application.

希望这会有所帮助。

这篇关于使用Java在运行时加载CA根证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆