Java Application using Https Connection:"Connection refused error" - java

I have created a jar for my JavaAppliaction.From this application I am connecting to servlet (I am passing name and password from swing to servlet) in the WebApplicaton(here I am just displaying name and password in the servlet).
I am passing data over SSL connection(Https). It is working fine in my system.But when I tried to run jar in another system I am getting “Connection refused error”.
Note:Running jar in another system which passes data over http connection is working fine.
I have gone through this link which suggested me to create a “jssecacerts” file and paste it in $JAVA_HOME/jre/lib/security folder of the “another system”. But I am still getting same error. Why is this not working??

One possible solution: Try importing the public certificate into java default keystore using.
keytool -importcert -trustcacerts -file "path-to-public-cert" -keystore JAVA_HOME/jre/lib/security/cacerts
it will ask for keystore password default keystore password is "changeit"
You can obtain the public cert by opening your URL in a web browser (e.g chrome) click on the icon at the start of URL -> click certificate information -> details tab -> click export
button.
A better approach will be:
create a keystore using "keytool" available in JAVA_HOME/bin
Import your server's public cert in this keystore.
bundle the keystore with your app.
make a bat / sh file to run your jar providing a parameter to java command -Djavax.net.ssl.trustStore=/path-to-your-keystore
So every time your app will start it will use this custom keystore. so you don't have to copy jssecacerts file on each system your run your app on.

Related

Karaf: Connection refused (Corporate Proxy but proxy is correctly configured in Karaf/Maven)

I'm sitting behind a coorporate proxy that has its own certificate. E.g. when I want my Java runtime to be able to communicate with the outer world I need to import my "coorporate certificate" to the Java truststore e.g. with keytool -import -keystore %JAVA_HOME%/jre/lib/security/cacerts -trustcacerts -file coorp-cert.crt
How do I import this certificate to Apache Karaf (4.3.0)?
Background:
I cannot install features into Karaf. E.g. karaf#root()> feature:repo-add ecf results in the error Error executing command: Connection refused: connect : [...]. The proxy is configured correctly (tested with maven:summary which displays valid "HTTP Proxies" values). So I suspect the missing proxy certificate is causing this problem.
Okay, although the commands http:proxy-list and maven:summary displayed the correct proxy settings, I fixed the problem by appending -Dhttps.proxyHost=<proxy url> -Dhttps.proxyPort=<proxy port> in the line starting with set DEFAULT_JAVA_OPTS in the $KARAF_HOME/bin/karaf.bat file. Alternatively one can probably set the JAVA_OPTS or EXTRA_JAVA_OPTS variables before starting karaf (haven't tested the latter, though).
The certificate apparently wasn't the problem.

Http Client certificate authentication: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed [duplicate]

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());
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);
// ...
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
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://stackoverflow.com/a/19542614/32453
If you are using Apache HTTPClient you must disable it "differently" (sadly): https://stackoverflow.com/a/2703233/32453
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.
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.
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.
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
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.
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.
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
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,
Download the site cert,
Using Chrome
Using Firefox
Copy the certificate(ex:cert_file.cer) into the directory $JAVA_HOME\Jre\Lib\Security
Open CMD in Administrator and change the directory to $JAVA_HOME\Jre\Lib\Security
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]
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!
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.
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.
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
For me didn't work the recognized solution from this post: https://stackoverflow.com/a/9619478/4507034.
Instead, I managed to solve the problem by importing the certification to my machine trusted certifications.
Steps:
Go to the URL (eg. https://localhost:8443/yourpath) where the certification is not working.
Export the certification as described in the mentioned post.
On your windows machine open: Manage computer certificates
Go to Trusted Root Certification Authorities -> Certificates
Import here your your_certification_name.cer file.
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.
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.
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.
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.
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
We too had same issue and we did all following things.
Reimported Server SSL certificates.
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.
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.
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.
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.
curl -vs https://your_rest_path
echo | openssl s_client -connect your_domain:443
sudo apt-get install ca-certificates
curl -vs https://your_rest_path will now work!
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.
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) {
}
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 :)
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

Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath [duplicate]

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());
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);
// ...
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
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://stackoverflow.com/a/19542614/32453
If you are using Apache HTTPClient you must disable it "differently" (sadly): https://stackoverflow.com/a/2703233/32453
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.
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.
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.
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
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.
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.
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
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,
Download the site cert,
Using Chrome
Using Firefox
Copy the certificate(ex:cert_file.cer) into the directory $JAVA_HOME\Jre\Lib\Security
Open CMD in Administrator and change the directory to $JAVA_HOME\Jre\Lib\Security
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]
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!
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.
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.
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
For me didn't work the recognized solution from this post: https://stackoverflow.com/a/9619478/4507034.
Instead, I managed to solve the problem by importing the certification to my machine trusted certifications.
Steps:
Go to the URL (eg. https://localhost:8443/yourpath) where the certification is not working.
Export the certification as described in the mentioned post.
On your windows machine open: Manage computer certificates
Go to Trusted Root Certification Authorities -> Certificates
Import here your your_certification_name.cer file.
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.
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.
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.
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.
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
We too had same issue and we did all following things.
Reimported Server SSL certificates.
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.
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.
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.
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.
curl -vs https://your_rest_path
echo | openssl s_client -connect your_domain:443
sudo apt-get install ca-certificates
curl -vs https://your_rest_path will now work!
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.
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) {
}
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 :)
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

SocketException Default SSL context is null while connecting to remote server

I am facing the following SSL connection exception when trying to connect to remote server:
java.net.SocketException: Default SSL context init failed: null
Most of the thread suggest that there is some problem with the keystore location that contains the certificate file.
Others like this post: Default SSL context init failed: null suggests is to create the SSL Context by yourself. But, again the issue is not resolved yet.
And here is what I did so far:
I tried to add certificate to the following file locations and all of them gave me the same error mentioned earlier:
• Cacerts file in Java Home.
• Default cacerts location for the IDE I am using (JDveloper 10.1.3.2) which is in my case : C:\JDeveloper\WorkSpace_10g\jdevstudio10132\jdk\jre\lib\security\cacerts
• New keystore that only contains this certificate.
The certificated is added using Portecle applet( I also tried keytool options from Command prompts)
I am also referring to the trustStore and keyStore in the code as follow:
System.setProperty("javax.net.ssl.trustStore", trustStore file path goes here);
System.setProperty("javax.net.ssl.trustStorePassword", password goes here);
System.setProperty("javax.net.ssl.keyStore", keyStore file path goes here);
System.setProperty("javax.net.ssl.keyStorePassword", password goes here);
In the above code the file path refer for the cacerts files mentioned earlier (Java home, default JDeveloper cacerts and newly created keystore) of course I tried each one separately.
The keystore isn't found. Check that you can open that file from within the same piece of code by the same name you're using in javax.net.ssl.keyStore.
If you're using the default cacerts you don't need to set javax.net.ssl.trustStore/trustStorePassword at all.

How to test the code signing of a JAR file on a client machine?

We have signed a JAR file using a certificate generated by MS Active Directory Certificate Services. However, when accessing it via Java Web Start we are getting the prompt that the digital signature cannot be verified even though we've installed the root CA into the certificate store on the client machine.
Now trying to look at the root CA on the client machine, using "keytool -list", I'm seeing an exception (invalid URI:file://\my_msadcs_server\path\to\CRL.crl). So now I'm not sure exactly what is going wrong.
Anyone have a suggestion or sample Java code on how I can test the downloaded JAR file's signature on the client machine in an attempt to figure out exactly why JWS is complaining? It could be that the root CA certificate has a problem (and I will chase down that avenue when my AD admin gets in) but I'd like to rule out other possibilities first. Currently the only thing I have to go on is the exception from "keytool -list", but keytool had no issues importing the root CA certificate in the first place.
Thanks in advance!,
mG.
I use jarsigner with the -verify, -verbose and -certs options. You may have to specify your -keystore, too.
I think the invalid URI message is a clue. Java file URI takes the following form: file://host/path

Categories

Resources