Search code examples
google-cloud-functionsssl-certificatesslhandshakeexception

Google cloud function - trying 2 way ssl handshake but getting error unable to find valid certification path to requested target


I have my own clients Private key and certificate which I have put in keystore, and servers public certificate root and intermediate I have created truststore and put them into it. I am trying to ssl handshake but not able to do so. I have below code snippet not sure what went wrong

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
                KeyStore keystore = KeyStore.getInstance("JKS");
                keystore.load(keystoreStream, "mypass".toCharArray());
                kmf.init(keystore, "mypass".toCharArray());
                KeyManager[] keyManagers = kmf.getKeyManagers();
                keystoreStream.close();
                keystoreStream = null;
                
                
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                KeyStore truststore = KeyStore.getInstance("JKS");
                truststore.load(truststoreStream, "mypass".toCharArray());
                tmf.init(truststore);
                TrustManager[] trustManagers = tmf.getTrustManagers();
                truststoreStream.close();
                truststoreStream = null;
                
                SSLContext sslContext = SSLContext.getInstance("SSL");
                sslContext.init(keyManagers, trustManagers, null);
                
                if (urlConnection instanceof HttpsURLConnection) {
                    HttpsURLConnection httpURLConnection = (HttpsURLConnection) urlConnection;
                    httpURLConnection.setRequestMethod("POST");
                    httpURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());
                    //error on below line                   
                    httpURLConnection.connect();

                    OutputStreamWriter wr = new OutputStreamWriter(urlConnection.getOutputStream());
                    wr.write(requestData.toString());
                    wr.flush();

                    responseCode = httpURLConnection.getResponseCode();
                }
            }

Error -

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


Solution

  • The problem is caused by a certificate that is self-signed (a Certificate Authority did not sign it) or a certificate chain that does not exist within the Java truststore.

    As a workaround, you can add this certificate to the list of trusted certificates of your JVM.

    • First you can check if your certificate is already in the truststore by running the following command: keytool -list -keystore "$JAVA_HOME/jre/lib/security/cacerts" (you don't need to provide a password).

      If your certificate is missing, you can get it by downloading it with your browser and add it to the truststore with the following command:

      keytool -import -noprompt -trustcacerts -alias <AliasName> -file <certificate> -keystore <KeystoreFile> -storepass <Password>

      Alternatively you may refer to this thread.

    • It is important that you see that the correct truststore is in use. If -Djavax.net.ssl.trustStore has been configured, it will override the location of the default truststore, which will need to be checked.

    • Also,you may have multiple JRE/JDKs and that sometimes might be a source of confusion. Hence, make sure the certificates have been imported into the correct truststore.

    • Check if your Anti Virus tool has "SSL Scanning" blocking SSL/TLS. If it does, disable this feature or set exceptions for the target addresses.

    • Verify that the target server is configured to serve SSL correctly. This can be done with the SSL Server Test tool.

    • If the above fails, your truststore might be out of date. Upgrade Java to the latest version supported by your application.