Resolving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error?
Asked Answered
S

38

620

Edit : I tried to format the question and accepted answer in more presentable way at my blog.

Here is the original issue.

I am getting this error:

detailed message sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

cause 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 am using Tomcat 6 as webserver. I have two HTTPS web applications installed on different Tomcats on different ports but on the same machine. Say App1 (port 8443) and App2 (port 443). App1 connects to App2. When App1 connects to App2 I get the above error. I know this is a very common error so came across many solutions on different forums and sites. I have the below entry in server.xml of both Tomcats:

keystoreFile="c:/.keystore" 
keystorePass="changeit"

Every site says the same reason that certificate given by app2 is not in the trusted store of app1 jvm. This seems to be true also when I tried to hit the same URL in IE browser, it works (with warming, There is a problem with this web site's security certificate. Here I say continue to this website). But when same URL is hit by Java client (in my case) I get the above error. So to put it in the truststore I tried these three options:

Option 1

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

Option 2

Setting below in environment variable

CATALINA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

Option 3

Setting below in environment variable

JAVA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

Result

But nothing worked.

What at last worked is executing the Java approach suggested in How to handle invalid SSL certificates with Apache HttpClient? by Pascal Thivent i.e. executing the program InstallCert.

But this approach is fine for devbox setup but I can not use it at production environment.

I am wondering why three approaches mentioned above did not work when I have mentioned the same values in server.xml of App2 server and same values in truststore by setting

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore") and System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

in App1 program.

For more information this is how I am making the connection:

URL url = new URL(urlStr);

URLConnection conn = url.openConnection();

if (conn instanceof HttpsURLConnection) {

  HttpsURLConnection conn1 = (HttpsURLConnection) url.openConnection();
  
  conn1.setHostnameVerifier(new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
      return true;
    }
  });

  reply.load(conn1.getInputStream());
Standley answered 8/3, 2012 at 14:17 Comment(6)
possible duplicate of HttpClient and SSLPlagioclase
Odly enough I got this error when communicating between clustered servers that had no SSL problems individually. Once I properly set domainname in my RHEL servers the problem was gone. Hope it helps someone.Ornis
One other thing to check is that you have the latest version of Java - I was getting a similar error because of this.Eley
#2894319 - also relevant and a fantastic answer.Teniafuge
First of all import you'r crt file into {JAVA_HOME}/jre/security/cacerts, if you still faced with this exception, change you'r jdk version. For example from jdk1.8.0_17 to jdk1.8.0_231Toffee
I had this issue in windows, I found the answer here: #41257866Flashbulb
I
543

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.

Integrand answered 8/3, 2012 at 14:48 Comment(26)
ran command keytool -list -keystore %JAVA_HOME/lib/security/cacerts. and got the error keytool error: java.lang.Exception: Keystore file does not exist: %JAVA_HOME/lib /security/cacertsStandley
You'll have to use the full path, e.g. c:\java\jdk\lib\security\cacertsIntegrand
Like SimonSez said, you don't need a password, but if you want it, the default password is "changeit".Ardenia
Also, in Windows you need to run the terminal as administrator, otherwise you get the error keytool error: java.io.FileNotFoundException ... (Access is denied) when you try to import your certificate.Ardenia
Ah @Integrand you are my god. But to add to it, one must specify trust store location and password as mentioned by @M Sach to get it to work.Sensitive
@Dejel as for the filetype I always go with the *.cert filetype but AFAIK the Java keytool isn't picky. You're free to choose any name for the AliasName. Like a nickname, something like "MyCert" or "Spongebob". Cheers.Integrand
Continued to have issues with Java 1.8. Needed to add cert as described and use Java < 1.8Radiocommunication
@Integrand do I have to provide file path also? my .cer file is on my desktopKordofan
@Jesse you need to provide a path to any resource not in the scope (normally the dir) of the keytool script. So, without knowing your concrete setup, I would say yes. CheersIntegrand
I tested with JDK8(1.8.0_152) and it calls for a password.Kacykaczer
Shad see Felix commentIntegrand
The keytool program can be found in the java bin directory. If you start looking for it, like I did.Ancon
I imported this but I still get the same ValidationException. I verified in the trusted cacerts by trying to add again but it said Certificate not imported, alias already exists.Mobster
If you getting Certificate not imported, alias already exists error then you first need to delete that certificate using alias name like: keytool -delete -noprompt -trustcacerts -alias <AliasName> -file <certificate> -keystore <KeystoreFile> -storepass <Password>Subnormal
Hi folks i just want to add the keyword ATLASSIAN BAMBOO because this fixed my atlassian bamboo agent running on windows server. Adding this keyword to this page will probably help people find this working solution faster through search engines. Many thanks again for the explaination, works perfect.Dapper
I am getting keytool error: java.io.IOException: Invalid keystore formatFrailty
keytool -import -noprompt -trustcacerts -alias <AliasName> -file <certificate> -keystore <KeystoreFile> -storepass <Password> : Can you please a real example of the commands without <value>Rhombic
@Raulp: please see edited answer. Be aware that on a win machine you'll need to add the full path including the drive, e.g. C:\.... Also you'll need to run the command line as admin. Cheers!Integrand
@Integrand I tried everything and added the certificate it was working a day before but now i am again getting the same exception.. can you help me in this #66868758Pure
even after adding certificate, I am getting same errorConfluent
Yes the above command is working fine but if your certificate is PKCS12 and you get the error keytool error: java.lang.Exception: Input not an X.509 certificate then first apply this command openssl pkcs12 -clcerts -in certfile.p12 -out newcertfile.cer to convert it to valid format and then apply the above command for newcertfile.cer to add it to the java jre cacerts store.Revenue
keytool error: java.lang.Exception: Input not an X.509 certificateAvunculate
In your example command keytool -list -keystore "$JAVA_HOME/jre/lib/security/cacerts", we are listing all the trusted Certificate Authorities in the truststore called cacerts. So why is the -keystore argument named the way it is? Shouldn't it be -truststore?Urbina
I received keytool error: java.lang.Exception: Keystore file does not exist... - had to run keytool -list -keystore "$JAVA_HOME/lib/security/cacerts" (without the /jre/ path) instead to view my keystore.Practice
For me it worked when omitting the "keystore.jks" at the end. So in my case the path was /usr/lib/jvm/<jdk-dir>/cacerts. Certificate was added to keystoreFatuitous
You can also use this tool to import cert via UI keystore-explorer.org/downloads.htmlTasteless
V
244

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!!

Vociferant answered 21/9, 2012 at 5:50 Comment(13)
What do you do when the certificate expires? Repeat everything (yearly)?Adham
Consider using certificates that are valid for a longer time period? Like 50 Years for testing ;)Afterimage
Is there any way to do this programmatically?Honeyed
For people dealing with the PKIX error, "Path does not chain with any of the trust anchors", this solution did not solve that problem for me unfortunately.Myrticemyrtie
One Question - Does the aliasName is web address for which we are importing the certificate? For example, if URL is domain.site.com/pages/service.asmx then should alias be domain.site.com or complete URL(domain.site.com/pages/service.asmx) or should it also be prefixed with http:// or it is just an arbitrary name?Monetary
I am getting the same error, when I am calling Twitter source from flume. My jdk version is 1.8.0_45. What could be the problem because I have the latest jdk?Glisson
path:\lib\security> keytool -import -noprompt -trustcacerts -alias webCert -file webCertResource.cer -keystore c:/Users/Jackie/Desktop -storepass changeit I get "the system cannot find the file specified"Kordofan
If you get the error @Jesse had just ensure you run cmd with admin privilegesCsc
Nice, nice, nice and niiiiiice!Neptunian
This did not work for me right away, the next day it suddenly did, so maybe you need to turn off your JVM/PC and try againEpifaniaepifano
this worked for me I was getting PKIX errorBetelgeuse
FYI, cacerts file for Android Studio on MacOS is located in /Applications/Android Studio.app/Contents/jre/Contents/Home/lib/securitySilkweed
@Vociferant how can i get the HTTPS URL that Java could not access from the error because for my case i was building an apk and i don't know what url is being accessedChrome
E
63

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);

// ...
Elsie answered 18/8, 2015 at 14:10 Comment(6)
Step 2 did the trick for me using SpringBoot and Tomcat 7. Thank you.Savagery
Do I have to use keytool from java that is used by tomcat?because on one server I can have many javaLightproof
@Lightproof yes. You can also run it for all java dirs installed on your systemElsie
I get Keystore was tampered with, or password was incorrect error while -importing .crtFoliated
@prayagupd - maybe the store password is different? the default password is changeit. see https://mcmap.net/q/35993/-keytool-error-keystore-was-tampered-with-or-password-was-incorrect/3191896Elsie
instead of step 3, I run the following java command java -Djavax.net.ssl.trustStore="your_path_to_cacerts" -jar my_package.jar" and did the job.Auten
A
24

In my case the issue was that the webserver was only sending the certificate and the intermediate CA, not the root CA. Adding this JVM option solved the problem: -Dcom.sun.security.enableAIAcaIssuers=true

Support for the caIssuers access method of the Authority Information Access extension is available. It is disabled by default for compatibility and can be enabled by setting the system property com.sun.security.enableAIAcaIssuers to the value true.

If set to true, Sun's PKIX implementation of CertPathBuilder uses the information in a certificate's AIA extension (in addition to CertStores that are specified) to find the issuing CA certificate, provided it is a URI of type ldap, http, or ftp.

Source

Azikiwe answered 25/9, 2018 at 15:15 Comment(0)
S
13

It is possible to disable SSL verification programmatically. Works in a pinch for dev, but not recommended for production since you'll want to either use "real" SSL verification there or install and use your own trusted keys and then still use "real" SSL verification.

Below code works for me:

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

public class TrustAnyTrustManager implements X509TrustManager {

  public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
  }

  public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
  }

  public X509Certificate[] getAcceptedIssuers() {
    return null;
  }
}

             HttpsURLConnection conn = null;
             URL url = new URL(serviceUrl);
             conn = (HttpsURLConnection) url.openConnection();
             SSLContext sc = SSLContext.getInstance("SSL");  
             sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());  
                    // Create all-trusting host name verifier
             HostnameVerifier allHostsValid = new HostnameVerifier() {
               public boolean verify(String hostname, SSLSession session) {
                return true;
              }
            };
            conn.setHostnameVerifier(allHostsValid);

Or if you don't control the Connections underneath, you can also override SSL verification globally for all connections https://mcmap.net/q/35994/-how-to-fix-the-quot-java-security-cert-certificateexception-no-subject-alternative-names-present-quot-error

If you are using Apache HTTPClient you must disable it "differently" (sadly): https://mcmap.net/q/35915/-how-to-ignore-ssl-certificate-errors-in-apache-httpclient-4-0

Steve answered 11/5, 2018 at 4:29 Comment(4)
This code is totally insecure and should not be used.Plagioclase
@Plagioclase Why is it insecure? What is happening in the code briefly.Kiona
This is skipping all certificate validations, basically it's allowing any certificate to be accepted. The way certs work is that there's a root certificate (literally) physically protected, at various certifying authorities. This certificate is then used to issue other secondary certs, which can be validated all the way back to the root certifying authority. This is skipping all the upstream checks, meaning that I can send in any ssl cert (even self generated) and your application will accept it as secure, even though my identity as a url is not verified.Cartie
Thanks for your solution. You were lacking a line which actually uses sc which is an unused variable and therefore useless: conn.setSSLSocketFactory(sc.getSocketFactory());Grover
O
12

Another reason could be an outdated version of JDK. I was using jdk version 1.8.0_60, simply updating to the latest version solved the certificate issue.

Otherness answered 23/12, 2017 at 13:18 Comment(1)
I had the same problem too. Calling an API with a Lets Encrypt Certificate may not work with older versions of Java because it isn't recognized by the trusted root certification authorities. Updating Java will solve this issue.Anticatalyst
H
7

I was using jdk1.8.0_171 when I faced the same issue. I tried top 2 solutions here (adding a certificate using keytool and another solution which has a hack in it) but they didn't work for me.

I upgraded my JDK to 1.8.0_181 and it worked like a charm.

Hidrosis answered 25/7, 2018 at 3:33 Comment(0)
S
5

My cacerts file was totally empty. I solved this by copying the cacerts file off my windows machine (that's using Oracle Java 7) and scp'd it to my Linux box (OpenJDK).

cd %JAVA_HOME%/jre/lib/security/
scp cacerts mylinuxmachin:/tmp

and then on the linux machine

cp /tmp/cacerts /etc/ssl/certs/java/cacerts

It's worked great so far.

Semitone answered 26/7, 2013 at 20:3 Comment(4)
This works wonderfully if the problem is that you are using an older version of java which does not have the latest certificates.Nonessential
@Nonessential how about a Mac?Clevie
There was something seriously wrong with your Java installation if the cacerts file was empty. You should have reinstalled it all.Plagioclase
Perhaps, but this solution worked and nothing was ever wrong afterwards.Semitone
M
5

Using Tomcat 7 under Linux, this did the trick.

String certificatesTrustStorePath = "/etc/alternatives/jre/lib/security/cacerts";
System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

Under Linux, $JAVA_HOME is not always setup, but usually /etc/alternatives/jre points to $JAVA_HOME/jre

Midcourse answered 6/3, 2017 at 2:35 Comment(0)
B
5

DEPLOYABLE SOLUTION (Alpine Linux)

To be able to fix this issue in our application environments, we have prepared Linux terminal commands as follows:

cd ~

Will generate cert file in home directory.

apk add openssl

This command installs openssl in alpine Linux. You can find proper commands for other Linux distributions.

openssl s_client -connect <host-dns-ssl-belongs> < /dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > public.crt

Generated the needed cert file.

sudo $JAVA_HOME/bin/keytool -import -alias server_name -keystore $JAVA_HOME/lib/security/cacerts -file public.crt -storepass changeit -noprompt

Applied the generated file to the JRE with the program 'keytool'.

Note: Please replace your DNS with <host-dns-ssl-belongs>

Note2: Please gently note that -noprompt will not prompt the verification message (yes/no) and -storepass changeit parameter will disable password prompt and provide the needed password (default is 'changeit'). These two properties will let you use those scripts in your application environments like building a Docker image.

Note3 If you are deploying your app via Docker, you can generate the secret file once and put it in your application project files. You won't need to generate it again and again.

Banyan answered 10/2, 2020 at 10:38 Comment(0)
W
4

For me, this error appeared too while trying to connect to a process behind an NGINX reverse proxy which was handling the SSL.

It turned out the problem was a certificate without the entire certificate chain concatenated. When I added intermediate certs, the problem was solved.

Hope this helps.

Winters answered 23/4, 2017 at 14:20 Comment(3)
thats look like what im having. can you explain on how you added the intermediate certs and where. im using httpd revers proxy and not NGINX .Erv
this helped me in my case becasue im using httpd: access.redhat.com/solutions/43575Erv
With nginx, It only uses .key and .pem files for SSL config. First you convert .crt to .pem (simply: cp yourfile.crt yourfile.pem) and then for the SSL cert chain: you append .cer file to the last of .pem (cat yourfile.cer >> yourfile.pem)Tremann
T
4

for safety we should not use self signed certificates in our implementation. However, when it comes to development often we have to use trial environments which got self-signed certs. I tried to fix this issue programmatically in my code and I fail. However, by adding the cert to the jre trust-store fixed my issue. Please find below steps,

  1. Download the site cert,

  2. Copy the certificate(ex:cert_file.cer) into the directory $JAVA_HOME\Jre\Lib\Security

  3. Open CMD in Administrator and change the directory to $JAVA_HOME\Jre\Lib\Security

  4. Import the certificate to a trust store using below command,

keytool -import -alias ca -file cert_file.cer -keystore cacerts -storepass changeit

If you got a error saying keytool is not recognizable please refer this.

Type yes like below

Trust this certificate: [Yes]

  1. Now try to run your code or access the URL programmatically using java.

Update

If your app server is jboss try adding below system property

System.setProperty("org.jboss.security.ignoreHttpsHost","true");

Hope this helps!

Tanjatanjore answered 14/1, 2019 at 10:50 Comment(0)
C
4

If you are using JDK 11, the folder doesn't have JRE in it anymore. The location for the certs is jdk-11.0.11/lib/security/cacerts.

Club answered 7/6, 2021 at 23:52 Comment(0)
S
3

i wrote a small win32 (WinXP 32bit testet) stupid cmd (commandline) script which looks for all java versions in program files and adds a cert to them. The Password needs to be the default "changeit" or change it yourself in the script :-)

@echo off

for /F  %%d in ('dir /B %ProgramFiles%\java') do (
    %ProgramFiles%\Java\%%d\bin\keytool.exe -import -noprompt -trustcacerts -file some-exported-cert-saved-as.crt -keystore %ProgramFiles%\Java\%%d\lib\security\cacerts -storepass changeit
)

pause
Spokeshave answered 6/12, 2012 at 15:32 Comment(0)
M
3

This seems as good a place as any to document another possible reason for the infamous PKIX error message. After spending far too long looking at the keystore and truststore contents and various java installation configs I realised that my issue was down to... a typo.

The typo meant that I was also using the keystore as the truststore. As my companies Root CA was not defined as a standalone cert in the keystore but only as part of a cert chain, and was not defined anywhere else (i.e. cacerts) I kept getting the PKIX error.

After a failed release (this is prod config, it was ok elsewhere) and two days of head scratching I finally saw the typo, and now all is good.

Hope this helps someone.

Musette answered 19/5, 2020 at 15:29 Comment(0)
K
2

For MacOS X below is the exact command worked for me where I had to try with double hypen in 'importcert' option which worked :

sudo keytool -–importcert -file /PathTo/YourCertFileDownloadedFromBrowserLockIcon.crt -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/security/cacerts -alias "Cert" -storepass changeit
Kare answered 13/5, 2019 at 9:58 Comment(0)
O
2

I managed to solve the problem by importing the certification to my machine trusted certifications.

Steps:

  1. Go to the URL (eg. https://localhost:8443/yourpath) where the certification is not working.
  2. Export the certification as described in the mentioned post.
  3. On your windows machine open: Manage computer certificates
  4. Go to Trusted Root Certification Authorities -> Certificates
  5. Import here your your_certification_name.cer file.
Ocelot answered 28/11, 2019 at 11:3 Comment(0)
I
1

I have this problem too.

I tried almost everything by adding the SSL cert to .keystore, but, it was not working with Java1_6_x. For me it helped if we start using newer version of Java, Java1_8_x as JVM.

Incontestable answered 10/2, 2017 at 7:30 Comment(2)
Same for me. An update from Java 1.8.0_91 to 1.8.0_121 solved the problem. I got the exception by using Apache HTTPClient.Toor
I still have this issue using Oauth2 authenticationLavadalavage
L
1

I want to chime in since I have a QEMU environment where I have to download files in java. It turns out the /etc/ssl/certs/java/cacerts in QEMU does have problem because it does not match the /etc/ssl/certs/java/cacerts in the host environment. The host environment is behind a company proxy so the java cacerts is a customized version.

If you are using a QEMU environment, make sure the host system can access files first. For example you can try this script on your host machine first to see. If the script runs just fine in host machine but not in QEMU, then you are having the same problem as me.

To solve this issue, I had to make a backup of the original file in QEMU, copy over the file in host environment to the QEMU chroot jail, and then java could download files normally in QEMU.

A better solution would be mount the /etc into the QEMU environment; however I am not sure if other files will get impacted in this process. So I decided to use this ugly but easy work-around.

Levan answered 30/3, 2020 at 6:5 Comment(0)
S
1

My two cents: In my case, cacerts was not a folder, but a file, and also it was presents on two paths After discover it, error disappeared after copy the .jks file over that file.

# locate cacerts    
/usr/java/jdk1.8.0_221-amd64/jre/lib/security/cacerts
/usr/java/jre1.8.0_221-amd64/lib/security/cacerts

After backup them, I copy the .jks over.

cp /path_of_jks_file/file.jks /usr/java/jdk1.8.0_221-amd64/jre/lib/security/cacerts
cp /path_of_jks_file/file.jks /usr/java/jre1.8.0_221-amd64/lib/security/cacerts

Note: this basic trick resolves this error on a Genexus project, in spite file.jks is also on the server.xml file of the Tomcat.

Stylobate answered 3/12, 2020 at 13:46 Comment(0)
C
1

I am using flutter and received this error out of nowhere. So, what basically happens is that the lines within your dependencies within android/build.gradle file such as:

  classpath 'com.android.tools.build:gradle:4.1.0'
  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

require certification that the grade file downloads from the internet. But when there is something that's blocking the gradle to download those certificates, this is typically shown.

I tried exporting the certificate and adding it manually but it didn't seem to work for me. What worked for me, after countless head scratches, was disabling the proxies from your network preferences. It was somewhere mentioned that disabling Charles Proxy would fix it but at that moment, I was clueless what Charles was and what proxy was. And in my case, I did not have the Charles proxy thing so I went on with finding the proxies in the network preferences settings in Mac( it could be found somewhere in network settings for Windows). I had Socks enabled within the proxy. I disabled it and then again rebuilt the gradle and TA-DAH!!! It worked butter smooth.

There are a few things to remember. If you build your project right after disabling proxy without closing the network preferences tab, the disable proxies won't work and it will show the same error. Also if you've already built the project and you're running it again after disabling proxies, chances are it's gonna show the same error( could be due to IDE caches). How it worked for me: Restart the Mac, open a few tabs in the browser( for a few network calls), check the network preferences from system preferences>> wifi and disable proxies, close the system preferences app, and build the project.

Careless answered 15/7, 2021 at 12:27 Comment(0)
C
1

I was getting this error in Android Studio. SO i did this after a lot of research.

Password is changeit for cacert

Step 1 : Open CMD as Administrator

Step 2 : Type "Powershell"

Step 3 : start-process powershell -verb runas

Step 4 : Add all your Certificate in C:\Program Files\Android\Android Studio\jre\lib\security this location where cacert is available.

Step 5 : Go to Keytool directory Set-Location -Path "C:\Program Files\Android\Android Studio\jre\bin"

Step 6 : run this command in powershell .\keytool -importcert -trustcacerts -alias GiveNameforyourcertificate -file "C:\Program Files\Android\Android Studio\jre\lib\security\Replace With Your Certificate name.cer" -keystore cacerts

Step 7 : If Error comes as Certificate added (Access denied) then create a D drive partition(https://www.diskpart.com/windows-10/how-to-create-d-drive-from-c-drive-in-windows-10-0725.html) or move you file to d drive then add certificate

If you kept your file in D drive then only execute this

Step 8 : keytool -importcert -trustcacerts -alias Nameyourcertificate -file "D:\Certificatename.cer" -keystore cacerts

Step 9 : Check if certificate was added or not using this command .\keytool -list -keystore cacerts

Ceyx answered 14/5, 2022 at 4:13 Comment(1)
do you have this solution for macosChrome
H
1

We too had same issue and we did all following things.

  1. Reimported Server SSL certificates.
  2. Made sure weblogic is using the proper caecerts.

Finally our weblogic enabled weblogic DEBUG mode and found there is "NOT HANDSHAKED" exception.

Reason we found is , client system is using jdk 1.6 and server is using higher jdk version ( 1.8) because of which there is some TLS version mismatch causing the issue.

Weblogic team tweaked server configuration by adding following lines in server arguments.

-Djdk.tls.client.protocol=TLSv1.2 -DUseSunHttpHandler=true.
Hollyanne answered 27/12, 2022 at 16:59 Comment(0)
I
0

Looking on various certificates contents and the ones generated through the standard openssl procedure i noticed that the AutorityKeyIdentifier was set, for the openssl root certificate, to itself. Probably there is a way to overcome that...but i don't know it...

Then i developed a small application with Java11 & BouncyCastle to generate root certificates and keys, now on github: https://github.com/kendarorg/JavaCaCertGenerator

The root certificates generated with this tool DOES NOT CONTAINS the AuthorityKeyIdentifier and can be installed with keytool directly on the cacert store. When i create then the csr and the ext file with the domain names this will be validated against the cacert store containing the root.. and no more handshake exceptions!

May be the cacert does not allow a recursive AuthorityKeyIdentifier? I don'know but i'll appreciate some review :)

Immunogenic answered 20/1, 2022 at 16:3 Comment(0)
P
0

In my case Charles Mac Os Proxy was the issue.
Steps to resolve -

  1. If charles is activated/opened then go to "Proxy" menu, unselect "Mac OS X Proxy" option.
  2. Kill all java processes using "Activity Monitor" app and try again.
Partition answered 21/5, 2023 at 20:30 Comment(1)
yes this helped me too..Jacklynjackman
S
0

I ran into this issue today (same PKIX error) after setting up a brand new project and was completely confused since I had previously imported my security certificate for my organization using the steps outlined above. In fact, project performing a similar function did not have this issue.

I realized that the version of the MS SQL JDBC library Gradle was grabbing was the newest one (12.2.0.jre8 as of this answer) and my other project was using version 8.4.1.jre8. Once I specified the old version, I was up and running.

I realize this answer doesn't explain what about the new version is causing the issue but I'm hoping it helps someone in a pinch. I've wasted a lot of time on this already.

My project is using Spring Boot, Gradle wrapper, Java 8, JPA and MS SQL Server.

Spectacles answered 31/7, 2023 at 18:13 Comment(0)
C
0

I would like to suggest a simple alternative based on certificate ripper which I have built myself. It extracts the server certificate and adds it the cacert truststore of the jdk. See below for the command.

crip export jks -u=https://[HOST:[PORT] -d=$JAVA_HOME/jre/lib/security/cacerts

In some cases you need to run it with sudo or admin rights. It is available for Windows, Mac and Linux. Binaries can be found here: certificate ripper binaries

Crinum answered 24/11, 2023 at 8:16 Comment(0)
K
-1

For Tomcat running on Ubuntu server, to find out which Java is being used, use "ps -ef | grep tomcat" command:

Sample:

/home/mcp01$ **ps -ef |grep tomcat**
tomcat7  28477     1  0 10:59 ?        00:00:18 **/usr/local/java/jdk1.7.0_15/bin/java** -Djava.util.logging.config.file=/var/lib/tomcat7/conf/logging.properties -Djava.awt.headless=true -Xmx512m -XX:+UseConcMarkSweepGC -Djava.net.preferIPv4Stack=true -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/share/tomcat7/endorsed -classpath /usr/share/tomcat7/bin/bootstrap.jar:/usr/share/tomcat7/bin/tomcat-juli.jar -Dcatalina.base=/var/lib/tomcat7 -Dcatalina.home=/usr/share/tomcat7 -Djava.io.tmpdir=/tmp/tomcat7-tomcat7-tmp org.apache.catalina.startup.Bootstrap start
1005     28567 28131  0 11:34 pts/1    00:00:00 grep --color=auto tomcat

Then, we can go in to: cd /usr/local/java/jdk1.7.0_15/jre/lib/security

Default cacerts file is located in here. Insert the untrusted certificate into it.

Kempis answered 10/6, 2014 at 3:38 Comment(0)
A
-1

I was having this problem with Android Studio when I'm behind a proxy. I was using Crashlytics that tries to upload the mapping file during a build.

I added the missing proxy certificate to the truststore located at /Users/[username]/Documents/Android Studio.app/Contents/jre/jdk/Contents/Home/jre/lib/security/cacerts

with the following command: keytool -import -trustcacerts -keystore cacerts -storepass [password] -noprompt -alias [alias] -file [my_certificate_location]

for example with the default truststore password keytool -import -trustcacerts -keystore cacerts -storepass changeit -noprompt -alias myproxycert -file /Users/myname/Downloads/MyProxy.crt

Anthropophagi answered 8/10, 2019 at 8:8 Comment(0)
J
-1

Just a small hack. Update the URL in the file "hudson.model.UpdateCenter.xml" from https to http

<?xml version='1.1' encoding='UTF-8'?>
<sites>
  <site>
    <id>default</id>
    <url>http://updates.jenkins.io/update-center.json</url>
  </site>
</sites>
Jamesy answered 30/12, 2019 at 15:9 Comment(0)
L
-1
  • Make sure of your JVM location. There can be half a dozen JREs on your system. Which one is your Tomcat really using? Anywhere inside code running in your Tomcat, write println(System.getProperty("java.home")). Note this location. In <java.home>/lib/security/cacerts file are the certificates used by your Tomcat.
  • Find the root certificate that is failing. This can be found by turning on SSL debug using -Djavax.net.debug=all. Run your app and note from console ssl logs the CA that is failing. Its url will be available. In my case I was surprised to find that a proxy zscaler was the one which was failing, as it was actually proxying my calls, and returning its own CA certificate.
  • Paste url in browser. Certificate will get downloaded.
  • Import this certificate into cacerts using keytool import.
Lannie answered 4/1, 2021 at 1:23 Comment(0)
P
-1

I ran into this issue while making REST calls from my app server running in AWS EC2. The following Steps fixed the issue for me.

  1. curl -vs https://your_rest_path
  2. echo | openssl s_client -connect your_domain:443
  3. sudo apt-get install ca-certificates

curl -vs https://your_rest_path will now work!

Pukka answered 14/1, 2021 at 17:32 Comment(0)
S
-1

I also have the same problem on Apache Tomcat/7.0.67 and Java JVM Version: 1.8.0_66-b18. With upgrading Java to JRE 1.8.0_241 and it seems that the issue was solved.

Slackjawed answered 20/3, 2021 at 18:48 Comment(0)
T
-1

Watch out for great answer for @NDeveloper. I did copy-paste of course, changing the values and I was getting

Illegal option:  ?import

I did checkout the hyphens and I saw that on that answer was the hyphen using the ASCII

– 8211

If you are getting problems check that the ASCII code that did the trick for me was this code = 45

- 45

My code

keytool -import -noprompt -trustcacerts -alias Certificado -file "C:\Users\JavIut\Desktop\Company\Certificados\Certificado.cer" -keystore "C:\Program Files\Java\jdk1.8.0_121\jre\lib\security\cacerts"
Timon answered 27/8, 2021 at 14:23 Comment(0)
H
-1

For OkHttpClient, this solution worked for me. It might help someone using the library...

try {

            String proxyHost = "proxy_host";
            String proxyUsername = "proxy_username";
            String proxyPassword = "proxy_password";

            Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, "port goes here"));

            // Create a trust manager that does not validate certificate chains
            TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return new java.security.cert.X509Certificate[]{};
                    }
                    @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
            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            // Create an ssl socket factory with our all-trusting manager
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient client = new OkHttpClient().newBuilder()
                    .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0])
                    .hostnameVerifier((hostname, session) -> true)
                    .connectTimeout(timeout, TimeUnit.SECONDS)
                    .proxy(proxy)
                    .proxyAuthenticator((route, response) -> {
                        String credential = Credentials.basic(proxyUsername, proxyPassword);
                        return response.request().newBuilder()
                                .header("Proxy-Authorization", credential)
                                .build();
                    })
                    .build();

            MediaType mediaType = MediaType.parse("application/json");
            RequestBody requestBody = RequestBody.create(payload, mediaType);

            Request request = new Request.Builder()
                    .url(url)
                    .header("Authorization", "authorization data goes here")
                    .method(requestMethod, requestBody)
                    .build();

            Response response = client.newCall(request).execute();

            resBody = response.body().string();

            int responseCode = response.code();

        } catch (Exception ex) {
        }
Helmholtz answered 15/11, 2021 at 12:39 Comment(0)
S
-1

I have been searching about similar problem, because I need to serve angular application on local domain like as example.com as securely.

To create certificate,

openssl req  -newkey rsa:2048 -x509 -nodes -keyout server.key -new -out server.crt  -config ./openssl-custom.cnf -sha256  -days 3650

openss-custom.cnf

[req]
default_bits = 2048
prompt = no
default_md = sha256
x509_extensions = v3_req
distinguished_name = dn

[dn]
C = TR
ST = Ankara
L = Ankara
O = Example
OU = Angular
emailAddress = [email protected]
CN = *.example.com

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = *.example.com

Evenif I import this certificate to cacerts of the active jre, Spring boot application didn't work properly. And "trustAnchor must be non empty" error was throwed. Because jvm didn't contain my truststore. To solve this problem, truststore should be given to jvm parameter.

Set this parameters at spring boot side

@Configuration
public class SSLConfig {
    @Autowired
    private Environment env;

    @PostConstruct
    private void configureSSL() {
      //load the 'javax.net.ssl.trustStore' and
      //'javax.net.ssl.trustStorePassword' from application.properties
      System.setProperty("javax.net.ssl.trustStore", env.getProperty("server.ssl.trust-store")); 
      System.setProperty("javax.net.ssl.trustStorePassword",env.getProperty("server.ssl.trust-store-password"));
    }
}
application.properties:

server.ssl.trust-store: YOUR_TRUST_STORE_PATH
server.ssl.trust-store-password: YOUR_TRUST_STORE_PASSWORD

or set jvm parameter when run java application

-Djavax.net.ssl.trustStore
-Djavax.net.ssl.trustStorePassword
Slurry answered 27/4, 2023 at 6:11 Comment(0)
J
-1

I am running java code on Mac, Visual Code Studio. I tried all the options, the only thing that worked for me was replacing the alias with the website url.

after (worked)

sudo keytool -import -noprompt -trustcacerts -alias https://central.sonatype.com -file "" -keystore "/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home/lib/security/cacerts"

before

sudo keytool -import -noprompt -trustcacerts -alias CentralSonaType -file "" -keystore "/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home/lib/security/cacerts"

I created a launch configuration

 "vmArgs": [
                "-Djavax.net.debug=ALL",
                "-Djavax.net.ssl.keyStore=/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home/lib/security/cacerts",
                "-Djavax.net.ssl.keyStorePassword=changeit",
                "-Djavax.net.ssl.trustStore=/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home/lib/security/cacerts", 
                "-Djavax.net.ssl.trustStorePassword=changeit"
  ]
Jacklynjackman answered 2/11, 2023 at 19:21 Comment(0)
F
-3

In a pinch, you can disable SSL entirely, or per connection (note this is not recommended for production!) see https://mcmap.net/q/35994/-how-to-fix-the-quot-java-security-cert-certificateexception-no-subject-alternative-names-present-quot-error

Fillender answered 17/10, 2019 at 19:6 Comment(2)
Code-only answers are generally frowned upon on this site. Could you please edit your answer to include some comments or explanation of your code? Explanations should answer questions like: What does it do? How does it do it? Where does it go? How does it solve OP's problem?Analgesia
add this to your code No. Do not add this to your code. Creating an SSLContext in this manner removes all security checks that verify the identity of the server you are connecting to. The answer to the problem of losing your keys is NOT to remove all the locks from everything you own.Bumble

© 2022 - 2024 — McMap. All rights reserved.