How I can deactivate the SSL verification?

21,384

Solution 1

Try this

public void disableCertificates() {
    TrustManager[] trustAllCerts = new TrustManager[]{
        new X509TrustManager() {

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] certs, String authType) {
            }

            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] certs, String authType) {
            }
        }
    };

    // Install the all-trusting trust manager
    try {
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
    }
}

Solution 2

I need deactivate the SSL verification because the security methods is the API KEY that I already have.

It's not clear how you think the API key (and the security aspect it offers) has anything to do with the security offered by SSL/TLS: they're certainly not addressing the same security aspects. SSL/TLS is about protecting the data transmission from eavesdropping and alteration.

If you check the server you're trying to contact against this SSL testing service, you'll find that the server requires a client that supports Server Name Indication (SNI): this allows the server to host multiple hosts with different certificates.

If your client doesn't support SNI (Java only supports it on the client side from version 7), the requests will be presented with a different certificate than the one indented: it may fail either the certificate verification or the host name verification procedures. Disabling either checks makes the connection vulnerable to Man-In-The-Middle attacks.

  • I'd say the most likely cause for the problem you're having is that you're using a version of Java that doesn't support SNI (e.g. Java 6).

  • It's also possible that the JRE you're using doesn't have this particular CA in its default trust store. You could try to get an convert a list of CA certificates you're willing to trust from another source (e.g. Mozilla bundle, as often recommended with cURL). You may need to understand what CA certificates are first.

    As the JSSE reference guide says:

    IMPORTANT NOTE: The JDK ships with a limited number of trusted root certificates in the /lib/security/cacerts file. As documented in keytool, it is your responsibility to maintain (that is, add/remove) the certificates contained in this file if you use this file as a truststore.

    Depending on the certificate configuration of the servers you contact, you may need to add additional root certificate(s). Obtain the needed specific root certificate(s) from the appropriate vendor.

Either way: deactivating SSL verification isn't the solution to your problem.

EDIT:

It looks like the service you're trying to use has a certificate issued by StartSSL, which isn't one of the CAs bundled by default with the Oracle JRE apparently.

You'll need to download it from StartSSL (or export it from a trusted bundle you already have, it's called "StartCom ...") and import it into your cacerts store with keytool (or another trust store if you're using a different one):

keytool -import -keystore /path/to/jre/lib/security/cacerts -alias startssl -file startssl.crt

(Adapt the path and the name of the startssl certificate file as required, of course.)

Share:
21,384
Juan Rojas Montserrat
Author by

Juan Rojas Montserrat

Updated on July 09, 2022

Comments

  • Juan Rojas Montserrat
    Juan Rojas Montserrat almost 2 years

    I'm trying to make a call to REST API, but I get the following exception (Complete StackTrace at the end):

    "javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"
    

    I asked the API provider about this problem and says that there is something wrong with the SSL library That you are using.

    How would you solve this problem? With this same code (below) I did make calls to the NIMBLE API REST without problems, but in this case it does not work. Then, I do not have any file cert (.cer).

    I need deactivate the SSL verification because the security methods is the API KEY that I already have.

    Any suggestions?

    Thank you very much!

    ==== Console: ====

    POST https://api.nexalogy.com/project/create?api_key=XXXXXXXXXXXXXXXXXXXX
    HTTP Header:"Content-Type" "application/json"
    HTTP Body:[{"name":"project1","lang":"en","type":"twitter"}]
    api_key:XXXXXXXXXXXXXXXXXXXX
    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    

    I have also tried the following form and exception is the same:

    POST https://api.nexalogy.com/project/create
    HTTP Header:"Content-Type" "application/json"
    HTTP Header:"api_key" "XXXXXXXXXXXXXXXXXXXX"
    HTTP Body:[{"name":"project1","lang":"en","type":"twitter"}]
    api_key:XXXXXXXXXXXXXXXXXXXX
    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    

    ==== The code: ====

    package servlet;
    
    import java.io.BufferedReader;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet("/AddProject")
    public class AddProject extends HttpServlet {
        private static final long serialVersionUID = 1L;
        public AddProject() {
        }
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        }
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String body="[{\"name\":\"project1\",\"lang\":\"en\",\"type\":\"twitter\"}]";
            String api_key="XXXXXXXXXXXXXXXXXXXX";
            String str_response="";
            String line="";
            URL url = new URL("https://api.nexalogy.com/project/create?api_key="+api_key);
            try{
                HttpURLConnection connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("POST");
                connection.setRequestProperty("Content-Type","application/json");
                System.out.println("POST https://api.nexalogy.com/project/create?api_key="+api_key);
                System.out.println("HTTP Header:"+"\"Content-Type\" \"application/json\"");
                System.out.println("HTTP Body:"+body);
                System.out.println("api_key:"+api_key);
                connection.setUseCaches(false);
                connection.setDoInput(true);
                connection.setDoOutput(true);
                DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
                wr.writeBytes(body);
                wr.flush();
                wr.close();
                InputStream is = connection.getInputStream();
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader rd = new BufferedReader(isr);
                while ((line = rd.readLine()) != null) str_response+= line + '\r';
                rd.close();
                System.out.println("str_response:"+str_response);
            }catch(Exception e){
                e.printStackTrace(System.out);
                //throw new RuntimeException(e);
            }
        }
    }
    

    ==== Complete StackTrace: ====

    com.sun.jersey.api.client.ClientHandlerException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:131)
        at com.sun.jersey.api.client.Client.handle(Client.java:616)
        at com.sun.jersey.api.client.WebResource.handle(WebResource.java:559)
        at com.sun.jersey.api.client.WebResource.post(WebResource.java:230)
        at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.tREST_2Process(Twitter_api_create_project.java:955)
        at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.tJava_1Process(Twitter_api_create_project.java:635)
        at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.runJobInTOS(Twitter_api_create_project.java:1641)
        at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.main(Twitter_api_create_project.java:1494)
    Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
        at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
        at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
        at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
        at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
        at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
        at com.sun.jersey.client.urlconnection.URLConnectionClientHandler$1$1.getOutputStream(URLConnectionClientHandler.java:203)
        at com.sun.jersey.api.client.CommittingOutputStream.commitWrite(CommittingOutputStream.java:117)
        at com.sun.jersey.api.client.CommittingOutputStream.write(CommittingOutputStream.java:89)
        at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
        at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
        at sun.nio.cs.StreamEncoder.implFlush(Unknown Source)
        at sun.nio.cs.StreamEncoder.flush(Unknown Source)
        at java.io.OutputStreamWriter.flush(Unknown Source)
        at java.io.BufferedWriter.flush(Unknown Source)
        at com.sun.jersey.core.util.ReaderWriter.writeToAsString(ReaderWriter.java:191)
        at com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider.writeToAsString(AbstractMessageReaderWriterProvider.java:128)
        at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:88)
        at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:58)
        at com.sun.jersey.api.client.TerminatingClientHandler.writeRequestEntity(TerminatingClientHandler.java:305)
        at com.sun.jersey.client.urlconnection.URLConnectionClientHandler._invoke(URLConnectionClientHandler.java:182)
        at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:129)
        ... 7 more
    Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
        at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
        at sun.security.validator.Validator.validate(Unknown Source)
        at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(Unknown Source)
        at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
        at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
        ... 35 more
    Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
        at java.security.cert.CertPathBuilder.build(Unknown Source)
        ... 41 more
    

    EDITED 2013-06-13 Solution: implements X509TrustManager

    Add the following code ...

    HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
    connection.setRequestMethod("POST");
    connection.setUseCaches(false);
    connection.setDoInput(true);
    connection.setDoOutput(true);
    if (connection instanceof HttpsURLConnection) {
        try {
            KeyManager[] km = null;
            TrustManager[] tm = {new RelaxedX509TrustManager()};
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, tm, new java.security.SecureRandom());
            SSLSocketFactory sf = sslContext.getSocketFactory();
            ((HttpsURLConnection)connection).setSSLSocketFactory(sf);
            System.out.println("setSSLSocketFactory OK!");
        }catch (java.security.GeneralSecurityException e) {
            System.out.println("GeneralSecurityException: "+e.getMessage());
        }
    }
    

    ... and add the following class (implements X509TrustManager)

    class RelaxedX509TrustManager implements X509TrustManager {
        public boolean isClientTrusted(java.security.cert.X509Certificate[] chain){ return true; }
        public boolean isServerTrusted(java.security.cert.X509Certificate[] chain){ return true; }
        public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; }
        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String input) {}
        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String input) {}
    }
    
    • Bruno
      Bruno almost 11 years
      Which version of Java are you using?
    • Juan Rojas Montserrat
      Juan Rojas Montserrat almost 11 years
      Hi, thanks for you reply, I saw your comment, I used java6, now I installed and configured java7 but the error is still the same :/ I'll have to try the second option you mention.
    • Juan Rojas Montserrat
      Juan Rojas Montserrat almost 11 years
      I had to implement the "X509TrustManager" Interface (docs.oracle.com/javase/6/docs/api/javax/net/ssl/…), and upgrade to java7, these two things were the solution, now work fine. Thanks!
    • Bruno
      Bruno almost 11 years
      Your RelaxedX509TrustManager doesn't check anything (and its isClientTrusted and isServerTrusted methods won't be used): it's insecure. Don't use this solution.
    • Juan Rojas Montserrat
      Juan Rojas Montserrat almost 11 years
      I agree, Do you have any suggestion?
    • Bruno
      Bruno almost 11 years
      Yes, I've edited my answer.
    • Juan Rojas Montserrat
      Juan Rojas Montserrat almost 11 years
      Thanks @Bruno, your comment update solve it!
    • Vadzim
      Vadzim almost 6 years
  • Uwe Plonus
    Uwe Plonus almost 11 years
    Please don't use this code in a production environment as it disables all certificate checking. Therefore your implementation is then vulnerable to MITM attacks.
  • Juan Rojas Montserrat
    Juan Rojas Montserrat almost 11 years
    Hi! thanks for you reply, I tried with this code, import javax.net.ssl.TrustManager and javax.net.ssl.X509TrustManager, and I call this method before my code, but the exception still saying the same.
  • user207421
    user207421 almost 11 years
    That's not correct. All that's needed is any of the signer certificates, imported as 'trusted'. Typically, the highest one is imported. The peer should send the rest of the chain along with its certificate.
  • user207421
    user207421 almost 11 years
    Please don't use this code at all. There's no point in deploying an insecure solution even just to test it. You're running the risk of it 'leaking' into production, which would be a major security breach. Also the code ignores exceptions and violates the contract of TrustManager. Avoid.
  • Uwe Plonus
    Uwe Plonus almost 11 years
    @EJP I wrote that at least the root certificate is needed (in the first paragraph). I corrected the second paragraph to clarify this.
  • Akintayo Olusegun
    Akintayo Olusegun almost 11 years
    You guys are missing the point, he wants to disable SSL verification and disable verification the above code did. If he is concerned about security he won't want to disable SSL verification in the first place. arrrgh.
  • Phil
    Phil over 10 years
    @Aardvocate Akintayo Olusegun you are totally right, however, the OP probably wanted to disable SSL verification for the same reason I did - it just didn't work! However, the problem is solvable in this specific instance (and mine) by simply doing Oracle's work for them - importing StartSSL's root cert.