在 Java 中在运行时加载 CA 根证书
Load CA root certificate at runtime in Java
tl;dr:使用自定义 CA 而不将其添加到持久密钥库。
我正在编写一个 Java 应用程序,它应该使用 HTTPS 连接到远程服务器。连接代码已准备就绪,但是服务器的 SSL 证书是由 StartSSL 签署的,它不在 Java 的 CA 根证书库中。
使用 this code,我从 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/
)。
当然,我可以使用 keytool
(甚至可能使用 Runtime.exec("keytool ...")
)手动将证书添加到密钥库,但这是一种肮脏的方式。我现在计划的是将 StartSSL 根证书添加到我的应用程序文件中以供分发,然后在运行时将其加载到某个临时密钥库中。这样 "real" 密钥库保持不变。
据我所读here and here, I will have to mess with some classes like TrustManager
. I even found a way to completely turn off the validation,但这不是我想要的,因为它似乎消除了加密通信的全部目的。
我什至发现一些代码行似乎完全符合我的要求,但我不知道如何调用此方法,即传递哪些值作为参数:
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);
}
}
有没有人遇到过类似的情况?我将不胜感激有关如何处理此问题的任何建议。如果你能帮我得到上面的代码运行,我会很高兴!
您将需要创建一个您已经找到的自定义 TrustStore。
除此之外,您还需要创建一个使用您提到的自定义信任管理器的自定义 SSL 套接字工厂,并将其注册到您正在使用的 HTTP 框架。细节真的取决于你选择的框架。
使用 keytool 实用程序将证书添加到默认密钥库没有错。您可能会发现需要多个证书。如果是这种情况,您必须确保整个 Java 应用程序使用相同的密钥存储作为单一事实来源。如果您在同一个应用程序中使用多个密钥存储,它可能会变得非常棘手。
希望对您有所帮助。
这对我有用!
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);
}
或者,另一种选择是使用 "portecle-1.9"
1.1 – Baixar o programa “portecle-1.9”.
1.1.1 https://sourceforge.net/projects/portecle
1.2 - Acessar a pasta security do JDK que será utilizado para rodar a aplicação
1.2.1 Exemplo: C:\Program Files\Java\jdk1.7.0_67\jre\lib\security
1.2.2 Fazer backup do arquivo “cacerts” (Só por segurança)
1.3 - Abrir o programa portecle “portecle.jar”
1.3.1 Acessar o “Menu > File > Open Keystore File..”
1.3.2 Selecione o arquivo “cacerts” mande abrir
1.3.3 Irá pedir senha, a senha padrão quando instala o JDK é “changeit”
1.3.4 O programa irá listar os diversos certificados contidos no “cecerts”
1.3.5 Acessar o “Menu > Tools > Import Trusted Certificate…”
1.3.6 Selecione o arquivo de certificado “.pem“ ou “.cer” ou alguma outra extensão compatível.
1.3.7 Será questionado se realmente o arquivo é “trusted” ou seja “confiável” . Aceita como confiavel.
1.3.8 Também será possível alterar o “alias”, provavelmente não será necessário mudar então apenas aceites todas as opções até que receba a mensagem “Certificado importado”.
1.3.9 Clique em “Salvar”, pois se não salvar as alterações não terão efeito!
tl;dr:使用自定义 CA 而不将其添加到持久密钥库。
我正在编写一个 Java 应用程序,它应该使用 HTTPS 连接到远程服务器。连接代码已准备就绪,但是服务器的 SSL 证书是由 StartSSL 签署的,它不在 Java 的 CA 根证书库中。
使用 this code,我从 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/
)。
当然,我可以使用 keytool
(甚至可能使用 Runtime.exec("keytool ...")
)手动将证书添加到密钥库,但这是一种肮脏的方式。我现在计划的是将 StartSSL 根证书添加到我的应用程序文件中以供分发,然后在运行时将其加载到某个临时密钥库中。这样 "real" 密钥库保持不变。
据我所读here and here, I will have to mess with some classes like TrustManager
. I even found a way to completely turn off the validation,但这不是我想要的,因为它似乎消除了加密通信的全部目的。
我什至发现一些代码行似乎完全符合我的要求,但我不知道如何调用此方法,即传递哪些值作为参数:
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);
}
}
有没有人遇到过类似的情况?我将不胜感激有关如何处理此问题的任何建议。如果你能帮我得到上面的代码运行,我会很高兴!
您将需要创建一个您已经找到的自定义 TrustStore。 除此之外,您还需要创建一个使用您提到的自定义信任管理器的自定义 SSL 套接字工厂,并将其注册到您正在使用的 HTTP 框架。细节真的取决于你选择的框架。
使用 keytool 实用程序将证书添加到默认密钥库没有错。您可能会发现需要多个证书。如果是这种情况,您必须确保整个 Java 应用程序使用相同的密钥存储作为单一事实来源。如果您在同一个应用程序中使用多个密钥存储,它可能会变得非常棘手。
希望对您有所帮助。
这对我有用!
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);
}
或者,另一种选择是使用 "portecle-1.9"
1.1 – Baixar o programa “portecle-1.9”.
1.1.1 https://sourceforge.net/projects/portecle
1.2 - Acessar a pasta security do JDK que será utilizado para rodar a aplicação
1.2.1 Exemplo: C:\Program Files\Java\jdk1.7.0_67\jre\lib\security
1.2.2 Fazer backup do arquivo “cacerts” (Só por segurança)
1.3 - Abrir o programa portecle “portecle.jar”
1.3.1 Acessar o “Menu > File > Open Keystore File..”
1.3.2 Selecione o arquivo “cacerts” mande abrir
1.3.3 Irá pedir senha, a senha padrão quando instala o JDK é “changeit”
1.3.4 O programa irá listar os diversos certificados contidos no “cecerts”
1.3.5 Acessar o “Menu > Tools > Import Trusted Certificate…”
1.3.6 Selecione o arquivo de certificado “.pem“ ou “.cer” ou alguma outra extensão compatível.
1.3.7 Será questionado se realmente o arquivo é “trusted” ou seja “confiável” . Aceita como confiavel.
1.3.8 Também será possível alterar o “alias”, provavelmente não será necessário mudar então apenas aceites todas as opções até que receba a mensagem “Certificado importado”.
1.3.9 Clique em “Salvar”, pois se não salvar as alterações não terão efeito!