【问题标题】:Java Exception on SSLSocket creation创建 SSLSocket 时出现 Java 异常
【发布时间】:2014-03-15 11:17:15
【问题描述】:

在代码中:

System.setProperty("javax.net.ssl.trustStore", cacerts);
System.setProperty("javax.net.ssl.trustStorePassword", pwdCacerts);

SSLSocketFactory sslsocketfactory = (SSLSocketFactory)  SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("localhost", port);

我得到一个 Java 异常:

java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
    at javax.net.ssl.DefaultSSLSocketFactory.throwException(Unknown Source)
    at javax.net.ssl.DefaultSSLSocketFactory.createSocket(Unknown Source)
    at PracticaRO.Cliente.main(Cliente.java:24)
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
    at java.security.Provider$Service.newInstance(Unknown Source)
    at sun.security.jca.GetInstance.getInstance(Unknown Source)
    at sun.security.jca.GetInstance.getInstance(Unknown Source)
    at javax.net.ssl.SSLContext.getInstance(Unknown Source)
    at javax.net.ssl.SSLContext.getDefault(Unknown Source)
    at javax.net.ssl.SSLSocketFactory.getDefault(Unknown Source)
    at PracticaRO.Cliente.main(Cliente.java:23)
Caused by: java.io.IOException: Invalid keystore format
    at sun.security.provider.JavaKeyStore.engineLoad(Unknown Source)
    at sun.security.provider.JavaKeyStore$JKS.engineLoad(Unknown Source)
    at java.security.KeyStore.load(Unknown Source)
    at sun.security.ssl.TrustManagerFactoryImpl.getCacertsKeyStore(Unknown Source)
    at sun.security.ssl.SSLContextImpl$DefaultSSLContext.getDefaultTrustManager(Unknown Source)
    at sun.security.ssl.SSLContextImpl$DefaultSSLContext.<init>(Unknown Source)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at java.lang.Class.newInstance(Unknown Source)
    ... 7 more

在我使用 -keytool -import -keystore cacerts -alias kpServer type JCEKS -file Server.cer 将新的公钥导入到 cacerts 之前,它工作正常,是导致上述异常的原因。

提前感谢您的帮助。

【问题讨论】:

    标签: java keytool truststore sslsocketfactory


    【解决方案1】:

    我将引导您完成设置过程。我建议你对所有事情都使用一个密码,只是为了你一开始不要混淆它。

    请按照以下步骤操作:
    1. 在命令行上:

    使用 RSA 创建公钥/私钥对,2048 位,实体名称为“secureEntity”,存储在文件“server.keyStore”中。
    1.1 keytool -genkeypair -alias secureEntity -keyalg RSA -keysize 2048 - keystone server.keyStore

    该命令为“secureEntity”存储了一个私钥和一个公钥。
    私钥,只有您才能访问它(通过知道文件密码)。
    公钥存储为证书,因此它遵循 X509 证书协议字段。这样我们就可以假设它包含一个公钥,并且这个公钥与“secureEntity”相关联。
    这就是我们需要知道的,以验证服务器发送给客户端的证书。
    SSL 第一步验证由客户端进行,因此客户端首先验证服务器。
    因此,现在我们已经生成了一个证书并将其存储在 server.keyStore 中,我们可以将其导出以便能够将其导入到一个或多个 trustStore。
    我们这样做的方式:
    1.2 keytool -exportcert -alias secureEntity -file exports.cer -keystore server.keystore

    所以现在我们可以添加到真正的 trustStore 文件中,它会在导入后要求我们确认我们确实信任该实体。如果文件不存在,它会自动创建。
    1.3 keytool -importcert -alias secureEntity -keystoretrustedEntities.trustStore -file exports.cer

    现在为方便起见,我们将其导入仅包含服务器证书的文件:
    1.4 keytool -importcert -alias secureEntity -keystore serverKeys.keyStore -file exports.cer

    所以现在你的服务器应该有一个私钥和公钥(证书)。

    在 JAVA 中:

    客户端:
    System.setProperty("javax.net.ssl.trustStore","trustedEntities.trustStore")
    并在此处创建 sslsocket

    服务器端:
    System.setProperty("javax.net.ssl.keyStore", "serverKeys.keyStore")
    System.setProperty("javax.net.ssl.keyStorePassword", "serverKeys.keyStore 之前定义的文件密码")

    创建一个服务器 ssl 就可以了。 希望这可以帮助。干杯!

    【讨论】:

      【解决方案2】:

      我从另一种方式得到了解决方案,我将它分享给遇到同样问题的人:

      我需要添加此代码

      System.setProperty("javax.net.ssl.trustStoreType","JCEKS");
      

      因为默认情况下它需要一个 JKS 类型。

      【讨论】:

        【解决方案3】:

        您导入的文件 (Server.cer) 不是 java 期望的格式。您告诉 keytool 格式是 JCEKS。我相信这意味着它是一个完整的密钥库,对于名为 Server.cer 的文件来说不太可能。

        您可能想改用 -type PKCS12。

        【讨论】:

          【解决方案4】:

          感谢您的回答... 通过输入此代码解决了我的问题:

          System.setProperty("javax.net.ssl.trustStoreType","JCEKS");
          

          代码如下:

          System.setProperty("javax.net.ssl.keyStore", CommonUtils.getKeystorePath());
          System.setProperty("javax.net.ssl.keyStorePassword", 
                             CommonUtils.getKeystorePassword());
          System.setProperty("javax.net.ssl.trustStore", 
                             CommonUtils.getTruststorePath());
          System.setProperty("javax.net.ssl.trustStorePassword", 
                             CommonUtils.getTruststorePassword());
          System.setProperty("javax.net.ssl.trustStoreType","JCEKS");
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-03-22
            • 1970-01-01
            • 2013-06-11
            • 2019-09-25
            • 2016-10-02
            • 2015-03-20
            • 2011-10-24
            • 1970-01-01
            相关资源
            最近更新 更多