Java Exception on SSLSocket creation

naxo picture naxo · Mar 15, 2014 · Viewed 27.1k times · Source

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.

Answer

Jo&#227;o Rodrigues picture João Rodrigues · Apr 15, 2016

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!