4

我正在与启用 ssl 的服务器建立 SSL 连接。我的硬件文件系统 java 密钥库中有一个 cacerts 文件,我使用 keytool 从中提取了证书,我正在提供此证书文件以创建 SSLSocketfactory 以建立 ssl 连接,它适用于下面的代码片段。

我想知道如何直接访问 cacerts ( java keystore ) 文件,然后选择证书并建立 ssl 连接。现在,我正在使用我的 jar 文件将提取的证书打包到类路径中,这不是一个好习惯,因为我希望它从密钥库中加载。

下面是我当前如何创建 SSLSocketFactory 的工作代码片段。

private SSLSocketFactory createSSLFactory() {
  KeyStore keyStore = null;
  TrustManagerFactory tmf = null;
  SSLContext ctx = null;

  try {
    keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    InputStream is = null;
    is = SSLConnection.class.getResourceAsStream("/" + "my-keystore");
    keyStore.load(is, "changeit".toCharArray());
    tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(keyStore);
    ctx = SSLContext.getInstance("TLSv1");
    ctx.init(null, tmf.getTrustManagers(), null);
    SSLSocketFactory factory = ctx.getSocketFactory();
    return factory;
  } catch (Exception e) {
    // exception handling
  }
  return null;
}
4

3 回答 3

4

在私钥和认证证书的情况下,将 KeyStore 嵌入到 JAR 文件中没有任何意义。客户端证书应该唯一标识客户端。它是主机的属性,而不是 JAR 文件,可以无限复制。允许多个客户端使用相同的客户端证书是没有意义的。这是对 PKI 的滥用。

于 2014-01-08T21:52:03.417 回答
1

您可以将密钥库(和信任库)作为系统属性传递给 JVM。见这里:https ://stackoverflow.com/a/882479/131929

-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.keyStore=clientcertificate.p12
-Djavax.net.ssl.trustStore=gridserver.keystore
-Djavax.net.debug=ssl # very verbose debug
-Djavax.net.ssl.keyStorePassword=$PASS
-Djavax.net.ssl.trustStorePassword=$PASS

然后你可以做

URL url = new URL("https://someurl");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
InputStream inputstream = conn.getInputStream();
于 2014-01-08T21:52:58.747 回答
0

您需要添加信任管理器:

            SSLSocketFactory factory = null;
        try {
            SSLContext ctx;
            KeyManagerFactory kmf;
            TrustManagerFactory tmf;
            KeyStore ks;
            char[] passphrase = "passphrase".toCharArray();

            ctx = SSLContext.getInstance("TLS");
            kmf = KeyManagerFactory.getInstance("SunX509");
            tmf = TrustManagerFactory.getInstance("SunX509");
            ks = KeyStore.getInstance("JKS");
            ks.load(new FileInputStream("testkeys"), passphrase);

            kmf.init(ks, passphrase);
            tmf.init(ks);
            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

            factory = ctx.getSocketFactory();
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }

        SSLSocket socket = (SSLSocket)factory.createSocket(host, port);
于 2020-12-17T03:54:40.463 回答