Java Exception on SSLSocket creation

2019-02-21 02:16发布

In the code:

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

I obtain a Java Exception:

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

It worked fine until I imported a new public key into cacerts with -keytool -import -keystore cacerts -alias kpServer type JCEKS -file Server.cer what caused the exception above.

Thanks in advance for any help.

4条回答
叼着烟拽天下
2楼-- · 2019-02-21 02:22

The file you imported (Server.cer) is not in the format java is expecting. You told keytool the format was JCEKS. I believe that means it's a full keystore, which is not likely for a file named Server.cer.

You may have wanted to use -type PKCS12 instead.

查看更多
forever°为你锁心
3楼-- · 2019-02-21 02:30

I'm going to walk you through setup process. I suggest you use one password for everything just for you not to get confuse with it at first.

Follow this steps:
1. On Command Line:

To create a Public/Private Key Pair using RSA, 2048 bits, entity name is "secureEntity", stored in file "server.keyStore".
1.1 keytool -genkeypair -alias secureEntity -keyalg RSA -keysize 2048 - keystone server.keyStore

That command stored a Private Key and a Public Key for "secureEntity".
The Private Key, only you should have access to it (by knowing file password).
The Public Key is stored as a Certificate, so it follows X509 Certificate protocol fields. That way we can assume it contains a public key, and this public key is associated to "secureEntity".
And this is what we need to know for us to validate the certificate sent by server to client.
SSL first step validation is made by client, so the client validates the server in first place.
So now that we have generated a certificate and it is stored in server.keyStore we can export it in order to be able to import it into one or more trustStore.
The way we do it:
1.2 keytool -exportcert -alias secureEntity -file exported.cer -keystore server.keystore

So now we can add to our really trustStore file, and it will ask us to confirm that we really trust that entity right after the import. If the file doesn't exists it well be automatically created.
1.3 keytool -importcert -alias secureEntity -keystore trustedEntities.trustStore -file exported.cer

Now for convenience lets import it to a file that only contains server certificate:
1.4 keytool -importcert -alias secureEntity -keystore serverKeys.keyStore -file exported.cer

So now your server should have a private and public key (certificate).

In JAVA:

Client Side:
System.setProperty("javax.net.ssl.trustStore","trustedEntities.trustStore")
and Create sslsocket here

Server Side:
System.setProperty("javax.net.ssl.keyStore", "serverKeys.keyStore")
System.setProperty("javax.net.ssl.keyStorePassword", "serverKeys.keyStore FILE PASSWORD THAT YOU DEFINED BEFORE")

Create a server ssl and thats it. Hope this helps. Cheers!

查看更多
趁早两清
4楼-- · 2019-02-21 02:41

I got the solution from another way, I share it for someone who comes here with the same problem:

I need add this code

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

because by default it expects a JKS type.

查看更多
对你真心纯属浪费
5楼-- · 2019-02-21 02:43

Thanks for your Answer... Solved my problem by putting this code :

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

Code as follows :

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");
查看更多
登录 后发表回答