Resolving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error?
You need to add the certificate for App2 to the truststore file of the used JVM located at %JAVA_HOME%\lib\security\cacerts
.
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>
Example:
keytool -import -noprompt -trustcacerts -alias myFancyAlias -file /path/to/my/cert/myCert.cer -keystore /path/to/my/jdk/jre/lib/security/cacerts/keystore.jks -storepass changeit
After import you can run the first command again to check if your certificate was added.
Sun/Oracle information can be found here.
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
• When I got the error, I tried to Google out the meaning of the expression and I found, this issue occurs when a server changes their HTTPS SSL certificate, and our older version of java doesn’t recognize the root certificate authority (CA).
• If you can access the HTTPS URL in your browser then it is possible to update Java to recognize the root CA.
• In your browser, go to the HTTPS URL that Java could not access. Click on the HTTPS certificate chain (there is lock icon in the Internet Explorer), click on the lock to view the certificate.
• Go to “Details” of the certificate and “Copy to file”. Copy it in Base64 (.cer) format. It will be saved on your Desktop.
• Install the certificate ignoring all the alerts.
• This is how I gathered the certificate information of the URL that I was trying to access.
Now I had to make my java version to know about the certificate so that further it doesn’t refuse to recognize the URL. In this respect I must mention that I googled out that root certificate information stays by default in JDK’s \jre\lib\security location, and the default password to access is: changeit.
To view the cacerts information the following are the procedures to follow:
• Click on Start Button-->Run
• Type cmd. The command prompt opens (you may need to open it as administrator).
• Go to your Java/jreX/bin
directory
• Type the following
keytool -list -keystore D:\Java\jdk1.5.0_12\jre\lib\security\cacerts
It gives the list of the current certificates contained within the keystore. It looks something like this:
C:\Documents and Settings\NeelanjanaG>keytool -list -keystore D:\Java\jdk1.5.0_12\jre\lib\security\cacerts
Enter keystore password: changeit
Keystore type: jks
Keystore provider: SUN
Your keystore contains 44 entries
verisignclass3g2ca, Mar 26, 2004, trustedCertEntry,
Certificate fingerprint (MD5): A2:33:9B:4C:74:78:73:D4:6C:E7:C1:F3:8D:CB:5C:E9
entrustclientca, Jan 9, 2003, trustedCertEntry,
Certificate fingerprint (MD5): 0C:41:2F:13:5B:A0:54:F5:96:66:2D:7E:CD:0E:03:F4
thawtepersonalbasicca, Feb 13, 1999, trustedCertEntry,
Certificate fingerprint (MD5): E6:0B:D2:C9:CA:2D:88:DB:1A:71:0E:4B:78:EB:02:41
addtrustclass1ca, May 1, 2006, trustedCertEntry,
Certificate fingerprint (MD5): 1E:42:95:02:33:92:6B:B9:5F:C0:7F:DA:D6:B2:4B:FC
verisignclass2g3ca, Mar 26, 2004, trustedCertEntry,
Certificate fingerprint (MD5): F8:BE:C4:63:22:C9:A8:46:74:8B:B8:1D:1E:4A:2B:F6
• Now I had to include the previously installed certificate into the cacerts.
• For this the following is the procedure:
keytool –import –noprompt –trustcacerts –alias ALIASNAME -file FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass PASSWORD
If you are using Java 7:
keytool –importcert –trustcacerts –alias ALIASNAME -file PATH_TO_FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass changeit
• It will then add the certificate information into the cacert file.
It is the solution I found for the Exception mentioned above!!
How to work-it in Tomcat 7
I wanted to support a self signed certificate in a Tomcat App but the following snippet failed to work
import java.io.DataOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class HTTPSPlayground {
public static void main(String[] args) throws Exception {
URL url = new URL("https:// ... .com");
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
httpURLConnection.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());
String serializedMessage = "{}";
wr.writeBytes(serializedMessage);
wr.flush();
wr.close();
int responseCode = httpURLConnection.getResponseCode();
System.out.println(responseCode);
}
}
this is what solved my issue:
1) Download the .crt
file
echo -n | openssl s_client -connect <your domain>:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/<your domain>.crt
- replace
<your domain>
with your domain (e.g.jossef.com
)
2) Apply the .crt
file in Java's cacerts
certificate store
keytool -import -v -trustcacerts -alias <your domain> -file ~/<your domain>.crt -keystore <JAVA HOME>/jre/lib/security/cacerts -keypass changeit -storepass changeit
- replace
<your domain>
with your domain (e.g.jossef.com
) - replace
<JAVA HOME>
with your java home directory
3) Hack it
Even though iv'e installed my certificate in Java
's default certificate stores, Tomcat ignores that (seems like it's not configured to use Java's default certificate stores).
To hack this, add the following somewhere in your code:
String certificatesTrustStorePath = "<JAVA HOME>/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);
// ...