0

I am creating a jax-ws client app that needs to accept self-signed certificates. But then there is this common SSL Handshake exception problem when you are trying to import self-signed certificates. So the most common work around for that is to extend the JSSE security provider and to initialize SSL context to accept all certificates like:

Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
TrustManager[] trustCerts = new TrustManager[]{new X509TrustManager() {
                        public X509Certificate[] getAcceptedIssuers() {
                            return null;
                        }

                       public void checkServerTrusted(X509Certificate[]
                       certs, String authType) throws CertificateException {
                            return;
                        }

                        public void checkClientTrusted(X509Certificate[]
                        certs, String authType) throws CertificateException {
                            return;
                        }
                    }
            }; 
SSLContext sc = SSLContext.getInstance("SSLv3");
sc.init(null, trustCerts, null);
SocketFactory factory = sc.getSocketFactory();
SSLSocket socket;
socket = (SSLSocket) factory.createSocket(mInstance.getHostName(),getSecureConnectionEndpoint().getPort());
socket.startHandshake();
setCerts(socket.getSession().getPeerCertificates());

This was the only workaround I could find to the problem. There are many similar kind of questions here such as Import SSL certificates and they all propose the same solution.

This is obviously very prone to man in the middle attack and this solution seems to be legit only for testing purposes.

So my question, is there no way of making this whole process more secure when you try to import certificates programmatically?

Thank you in advance!

Community
  • 1
  • 1
agenthost
  • 748
  • 2
  • 9
  • 24

3 Answers3

0

This is obviously very prone to man in the middle attack and this solution seems to be legit only for testing purposes.

Correct. It is radically insecure.

So my question, is there no way of making this whole process more secure when you try to import certificates programmatically?

Not if you do it via the channel you are trying to secure. A certificate to be trusted needs to be delivered by another means.

NB The code you posted doesn't satisfy the contract for getAcceptedIssuers(). It can't return null.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Thanks for your answer! But getAcceptedIssuers() has to return null so that the client can retrieve self-signed server certificates. – agenthost Jul 30 '15 at 09:59
  • 1
    That's not correct, and the Javadoc specifically states the contrary. Did you read it? – user207421 Jul 30 '15 at 21:47
0

Perhaps, rather than using self signed certificates, you would be better creating a certificate authority and trusting that?

I use XCA to run my own private CA and issue certificates - it's very easy to use and understand.

In order to get Java to trust your CA you need to import the root certificate - create the trust store using keytool

keytool -importcert -file myca.crt -keystore mykeystore.jks

Then import the trust store using the following JVM arg

-Djavax.net.ssl.trustStore=/home/user/mykeystore.jks
Rodney
  • 2,642
  • 1
  • 14
  • 15
  • Yes that's the easier way to do it. But the server side landscape could have multiple servers and it would be cumbersome to create a root certificate for each and every server. – agenthost Jul 30 '15 at 10:04
0

The encryption works same whether it is self signed or signed by CA. The only difference is if you self sign, it will display a warning that you are own our own to proceed on the site and the resulting server can decrypt your personal information and can use for malicious purposes. For self signing there is no way you can validate that the server is who it says it is. The data is encrypted whether it is self signed or signed by CA and for man in the middle attack I find no difference. It might be the case that someone is sniffing on the packets using wireshark or nmap etc but in both scenarios it is same whether it is self signed or signed by CA. Usually for dev and testing self signed certificate are used and in prod CA signed certificates are used. You don't want the end users to accept the risk associated with the site to save few dollars.

  If you are consuming the service in Java code you need to import the self 
 signed certificate in cacerts present in <PATH_TO_JRE>\lib\security\cacerts by
 the following command >keytool -import -alias <Alias Name> -file "PATH_TO_.crt"
 -keystore "PATH_TO_cacerts" -ext san=ip:127.0.0.1 

You can also use domain name like www.mydomain.com in san instead of ip

Goyal Vicky
  • 1,249
  • 16
  • 16