title: Getting SSL Handshake error even after installing & verifying the certificate
body: <p>I have the following Java program (Servlet) on Netbeans 8 where I am making an HTTP GET and sending some security credentials. I am running into the most common error that I found many people discussing. It used to run fine when I was using HTTP but now the server to which the URL is pointing to has been on HTTPS. Here is the error on Netbeans's Apache Tomcat or TomEE Log:</p>
  
  <p>=================================================================================
  <strong>My Error:</strong></p>
  
  <pre><code>01-Oct-2014 14:00:08.497 SEVERE [http-apr-8080-exec-8] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [My_API_Call] in context with path [/testapi] threw exception
   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 sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
      at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1917)
      at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:301)
      at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:295)
      at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1369)
      at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:156)
      at sun.security.ssl.Handshaker.processLoop(Handshaker.java:925)
      at sun.security.ssl.Handshaker.process_record(Handshaker.java:860)
      at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1043)
      at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1343)
      at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1371)
      at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1355)
      at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
      at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
      at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1511)
      at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1439)
      at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
      at My_API_Call.sendHttpRequest(My_API_Call.java:129)
      at My_API_Call.Group_GET(My_API_Call.java:82)
      at My_API_Call.doGet(My_API_Call.java:60)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:618)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:136)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
      at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:526)
      at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1078)
      at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:655)
      at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:277)
      at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2381)
      at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2370)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
      at java.lang.Thread.run(Thread.java:745)
  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(PKIXValidator.java:387)
      at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
      at sun.security.validator.Validator.validate(Validator.java:260)
      at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
      at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
      at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
      at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1351)
      ... 39 more
  Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
      at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:145)
      at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
      at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
      at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
      ... 45 more
  </code></pre>
  
  <p>==================================================================================
  <strong>My Program:</strong></p>
  
  <pre><code>import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.io.OutputStreamWriter;
  import java.io.PrintWriter;
  import java.net.URL;
  import java.net.URLConnection;
  import java.net.URLEncoder;
  import java.sql.Date;
  import java.text.DateFormat;
  import java.text.SimpleDateFormat;
  import java.util.ArrayList;
  import java.util.Calendar;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.TimeZone;
  import javax.crypto.Mac;
  import javax.crypto.spec.SecretKeySpec;
  import javax.servlet.ServletException;
  import javax.servlet.annotation.WebServlet;
  import javax.servlet.http.HttpServlet;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  import javax.crypto.Mac;
  import org.apache.commons.codec.binary.Hex;
  import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
  import com.google.gson.Gson;
  import com.google.gson.GsonBuilder;
  import org.json.JSONObject;
  
  @WebServlet("/My_API_Call")
  public class My_API_Call extends HttpServlet {
         public My_API_Call() {
          super();
         }
      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           response.setContentType("text/html;charset=UTF-8");
          // Allocate a output writer to write the response message into the network socket
          PrintWriter out = response.getWriter();
          // Write the response message, in an HTML page
          try {
              out.println("&lt;!DOCTYPE html&gt;");  // HTML 5
              out.println("&lt;html&gt;&lt;head&gt;");
              out.println("&lt;meta http-equiv='Content-Type' content='text/html; charset=UTF-8'&gt;");
              out.println("&lt;h3&gt;JSON Response&lt;/h3&gt;");
              out.println(new Gson().toJson(API_GET()));
              out.println("&lt;head&gt;&lt;title&gt;My API Call&lt;/title&gt;&lt;/head&gt;");
              out.println("&lt;body&gt;");
              // Tabulate the request information 
              out.println("&lt;/body&gt;&lt;/html&gt;");
          }   
          finally {
              out.close();  // Always close the output writer
          }
      }
      public static Object API_GET() throws IOException {
          String accessKey = "myaccesskey";
          String secretKey = "mysecretkey";
          String uRLCppList = "https://myapichecking.mydomain.com/webservice/testinggroup/133";
          String method = "GET";
          java.util.Date currentTime = new java.util.Date();
          SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
          sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
          String dateTimeString = sdf.format(currentTime);
          String signature = generateSignature(method, secretKey, dateTimeString);
          String authorization = accessKey + ":" + signature;
          Map&lt;String, String&gt; params = new HashMap&lt;String, String&gt;();
          String[] result = sendHttpRequest(uRLCppList, "POST", params, dateTimeString, authorization);
          return result;
      }
      public static String[] sendHttpRequest(String requestUrl, String method, Map&lt;String, String&gt; params, String dateTimeString, String authorization) throws IOException {
          List&lt;String&gt; response = new ArrayList&lt;String&gt;();
          StringBuffer requestParams = new StringBuffer();
          if (params != null &amp;&amp; params.size() &gt; 0) {
              Iterator&lt;String&gt; paramIterator = params.keySet().iterator();
              while (paramIterator.hasNext()) {
                  String key = paramIterator.next();
                  String value = params.get(key);
                  requestParams.append(URLEncoder.encode(key, "UTF-8"));
                  requestParams.append("=").append(URLEncoder.encode(value, "UTF-8"));
                  requestParams.append("&amp;");
              }
          }
          URL url = new URL(requestUrl);
          URLConnection urlConn = url.openConnection();
          urlConn.setRequestProperty("accept", "application/json");
          urlConn.setRequestProperty("datetime", dateTimeString);
          urlConn.setRequestProperty("authorization", authorization);
          urlConn.setUseCaches(false);
          // the request will return a response
          urlConn.setDoInput(true);
  
          if ("POST".equals(method)) {
              // set request method to POST
              urlConn.setDoOutput(true);
          } else {
              // set request method to GET
              urlConn.setDoOutput(false);
          }
          if ("POST".equals(method) &amp;&amp; params != null &amp;&amp; params.size() &gt; 0) {
              OutputStreamWriter writer = new OutputStreamWriter(urlConn.getOutputStream());
              writer.write(requestParams.toString());
              writer.flush();  
          }
          // reads response, store line by line in an array of Strings
          BufferedReader reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
  
          String line = "";
          while ((line = reader.readLine()) != null) {
              response.add(line);
          }
          reader.close();
          return (String[]) response.toArray(new String[0]);
      }
      public static String generateSignature(String method, String secretKey, String dateTimeString) {        
          String cs = String.format("%s\n\n\n%s\n\n\n", method, dateTimeString);
          String signature = createSignature(cs, secretKey);
          return  signature;
      }
      public static String createSignature(String stringIn, String scretKey) {
          String fixedData = stringIn.replace('\n', (char)10);
          // Calculate the hash of the information
          String digest = hmacSha1(scretKey, fixedData);
          return digest;
      } 
      public static String hmacSha1(String key, String value) {
          try {
              // Get an hmac_sha1 key from the raw key bytes
              byte[] keyBytes = key.getBytes("iso-8859-1");           
              SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1");
              // Get an hmac_sha1 Mac instance and initialize with the signing key
              Mac mac = Mac.getInstance("HmacSHA1");
              mac.init(signingKey);
              // Compute the hmac on input data bytes
              byte[] rawHmac = mac.doFinal(value.getBytes("iso-8859-1"));
              //  Covert array of Hex bytes to a String
              return Base64.encode(rawHmac);
             //return new String(hexBytes, "UTF-8");
          } 
          catch (Exception e) {
              throw new RuntimeException(e);
          }
      }
  }
  </code></pre>
  
  <p>I have referred to the following threads but most of them keeps on talking about installing the certificate into the trust store. And I have already installed the certificate on the machine where the aforementioned URL
  is referring to "<a href="https://myapichecking.mydomain.com/webservice/testinggroup/133" rel="nofollow noreferrer">https://myapichecking.mydomain.com/webservice/testinggroup/133</a>" . Say for example it is referring to an IP XX.XX.X.XXX, so I have installed the certificate over there but still getting the same error.</p>
  
  <p>1) <a href="https://stackoverflow.com/questions/9619030/resolving-javax-net-ssl-sslhandshakeexception-sun-security-validator-validatore">Resolving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error?</a></p>
  
  <p>2)<a href="http://www.java-samples.com/showtutorial.php?tutorialid=210" rel="nofollow noreferrer">http://www.java-samples.com/showtutorial.php?tutorialid=210</a></p>
  
  <p>Any idea what's going wrong with my API call ?</p>