Reputation: 8933
I have a Java client trying to access a server with a self-signed certificate.
When I try to Post to the server, I get the following error:
unable to find valid certification path to requested target
Having done some research on the issue, I then did the following.
Saved my servers domain name as a root.cer
file.
In my Glassfish server's JRE, I ran this:
keytool -import -alias example -keystore cacerts -file root.cer
To check the cert was added to my cacert successfully, I did this:
keytool -list -v -keystore cacerts
I can see the cert is present.
I then restarted Glassfish and retried the 'post'.
I am still getting the same error.
I have a feeling this is because my Glassfish is not actually reading the cacert
file that I have amended but maybe some other one.
Have any of you had this issue and can push me in the right direction?
Upvotes: 318
Views: 1669624
Reputation: 34
Export the self-signed certificate from the server:
openssl s_client -connect <server>:<port> -showcerts
This will output the certificate details. Copy the section between:
-----BEGIN CERTIFICATE-----
and:
-----END CERTIFICATE-----
(including the BEGIN and END lines)
Save this block to a file, e.g. my-cert.pem
.
Then import this file to your Java Keystore:
keytool -import -trustcacerts -alias my-cert -file /path/to/my-cert.pem -keystore <JAVA_HOME>/lib/security/cacerts
Restart your Java application, now it will be able to connect to the server.
You can refer to this article for more details on this procedure: How to Import Self-Signed Certificates into Java Keystore for Local Development.
Upvotes: -1
Reputation: 7704
Unfortunately - it could be many things - and lots of app servers and other java 'wrappers' are prone to play with properties and their 'own' take on keychains and what not. So it may be looking at something totally different.
Short of truss-ing - I'd try:
java -Djavax.net.debug=all -Djavax.net.ssl.trustStore=trustStore ...
to see if that helps. Instead of 'all' one can also set it to 'ssl', key manager and trust manager - which may help in your case. Setting it to 'help' will list something like below on most platforms.
Regardless - do make sure you fully understand the difference between the keystore (in which you have the private key and cert you prove your own identity with) and the trust store (which determines who you trust) - and the fact that your own identity also has a 'chain' of trust to the root - which is separate from any chain to a root you need to figure out 'who' you trust.
all turn on all debugging
ssl turn on ssl debugging
The following can be used with ssl:
record enable per-record tracing
handshake print each handshake message
keygen print key generation data
session print session activity
defaultctx print default SSL initialization
sslctx print SSLContext tracing
sessioncache print session cache tracing
keymanager print key manager tracing
trustmanager print trust manager tracing
pluggability print pluggability tracing
handshake debugging can be widened with:
data hex dump of each handshake message
verbose verbose handshake message printing
record debugging can be widened with:
plaintext hex dump of record plaintext
packet print raw SSL/TLS packets
Source: http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#Debug
Upvotes: 224
Reputation: 7181
In my case, jdbc
mssql
connection string add trustServerCertificate=true;
fix the issue.
Upvotes: 1
Reputation: 3
I' ve seen that using a relative path to point to cacerts wasn´t importing my trusted cert at all even if shown when listed using keytool list, using absolute path did the work(you can check it better using keystore explorer) pass is changeit
keytool -import -alias ca -file <<absolute_path>>\<<cacert>>.crt -keystore cacerts -storepass changeit
replace <<>> with values from your use case
Upvotes: 0
Reputation: 1010
I got the similar issue after figuring out for a while I find that I have not added my truststore in configurations so in my case this helped
I was using springboot gradle(kotlin) so you can add your truststore like this mine was present in resources folder.
tasks{
bootRun {
jvmArgs = listOf("-Djavax.net.ssl.trustStore=${projectDir}/src/main/resources/global_truststore.jks", "-Djavax.net.ssl.trustStorePassword=changeit",
"-Dspring.config.location=classpath:/")
}
}
Upvotes: 0
Reputation: 46904
Happened to me because my config included sslmode=verify-full
. You may need to change this to sslmode=require
. Or a programatic equivalent of that.
This also applies to using SSL/TLS from applications.
For instance, a Database client in IntelliJ IDEA's. There you need to go to the connection properties, SSH/SSL tab, and set Mode
to Require
.
More about SSL/TLS modes e.g here: https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/
Upvotes: 1
Reputation: 707
Because eclipse uses its own JRE, you should add certs to its own JRE keystore. I had this issue until I added certs to Sts's JRE.
`javax.net.ssl|DEBUG|1A|restartedMain|2021-12-06 23:04:00.874` IRST|TrustStoreManager.java:113|trustStore is: D:\sts-4.12.0.RELEASE\plugins\org.eclipse.justj.openjdk.hotspot.jre.full.win32.x86_64_16.0.2.v20210721-1149\jre\lib\security\cacerts
This is the full path: "sts-4.12.0.RELEASE\plugins\org.eclipse.justj.openjdk.hotspot.jre.full.win32.x86_64_16.0.2.v20210721-1149\jre\lib\security\cacerts"
Upvotes: 1
Reputation: 487
This is what I did.
I wanted to develop the app on Java 10, and I had the Eclipse IDE 2020-06. The cert import solution did not work for me. So then I installed Java 11 JDK, switched to the latest Eclipse IDE (which runs on Java 11), and made sure that the source-code still gets compiled against the Java 10, by adding these statemements under Maven POM:
<maven.compiler.target>1.10</maven.compiler.target>
<maven.compiler.source>1.10</maven.compiler.source>
<maven.compiler.release>10</maven.compiler.release>
And it works like a charm; no errors.
Upvotes: 0
Reputation: 19
I created a ubuntu on my windows 10 laptop and I ran into issue when I was trying to load CMAK site download from https://github.com/yahoo/CMAK site. First it gave fatal ssl error.
openssl s_client -showcerts -servername github.com -connect github.com:443 </dev/null 2>/dev/null | sed -n -e '/BEGIN\ CERTIFICATE/,/END\ CERTIFICATE/ p' > github-com.pem
and use the following command (make sure you put right path for ca-cert)
cat github-com.pem | sudo tee -a /etc/ssl/certs/ca-certificates.crt
Then use the following statement (make sure the path for cert is correct):
git config --global http.sslCAinfo /etc/ssl/certs/ca-certificates.crt
Then I was able to download CMAK but ran into issue when i tried ./sbt clean
statement. It was giving a pkix path
error. The reason is that I do not have my company issue cert stored in my cacert file.
I have downloaded the company cert (google on how to do it) and followed this article to add my downloaded cert to cacert file. Used sudo update-ca-certificates
one more time before ./sbt
. It worked for me.
Note: You may have to switch between root and exit when you are following above steps.
Upvotes: 0
Reputation: 312
Wasted a lot of time on that issue. If you imported the certificate and you can see it listed here.
keytool -list -v -keystore $JAVA_HOME/lib/security/cacerts
Then create the new one, with the following command, replace SITE_NAME, SITE_PORT, CERTIFICATE_NAME and path to save file.
echo -n | openssl s_client -connect SITE_NAME:SITE_PORT \
| openssl x509 > /path/to/save/CERTIFICATE_NAME.cert
In my case, I experienced problem using Keycloak with Spring. After I created certificate with this command and imported to keystore, the problem was solved and it works fine
Upvotes: 3
Reputation: 5649
I came across this error while trying to access a https
url from my application which was using self-signed certificate.
What they provide is a .cert
file and I was not sure where to put that. I solved it the following way:
keytool location is under JDK/bin folder
Method 1: Add the certificate to default Java Truststore - cacerts:
keytool -import -alias myCert -file C://certificate.cert -keystore C://Program Files//Java//jdk1.8.0_271//jre//lib//security//cacerts
Password: changeit
Method 2:
Create a Trust Store:
keytool -import -alias myCert -file C://certificate.cert -keystore myTrustStore
It gives you the following prompts, which can be filled up as:
Enter keystore password:changeit
Re-enter new password:changeit
Trust this certificate?yes
This will create a myTrustStore file inside a folder where you ran this command. Copy this "mytrustStore" to a convenient location.
Use the Trust Store:
While you are running your application/server pass these JVM arguments:
-Djavax.net.ssl.trustStore=C://myTrustStore -Djavax.net.ssl.trustStorePassword=changeit
Upvotes: 12
Reputation: 21
In my case, I was getting error connecting to AWS Gov Postgres RDS. There is a separate link for GOV RDS CA certs- https://s3.us-gov-west-1.amazonaws.com/rds-downloads/rds-combined-ca-us-gov-bundle.pem
Add this pem certs to cacerts of java. You can use below script.
------WINDOWDS STEPS-------
Script code:
#!/usr/bin/env sh
OLDDIR="$PWD"
CACERTS_FILE=cacerts
cd /c/rds-ca
echo "Downloading RDS certificates..."
curl https://s3.us-gov-west-1.amazonaws.com/rds-downloads/rds-combined-ca-us-gov-bundle.pem > rds-combined-ca-bundle.pem
csplit -sk rds-combined-ca-bundle.pem "/-BEGIN CERTIFICATE-/" "{$(grep -c 'BEGIN CERTIFICATE' rds-combined-ca-bundle.pem | awk '{print $1 - 2}')}"
for CERT in xx*; do
# extract a human-readable alias from the cert
ALIAS=$(openssl x509 -noout -text -in $CERT |
perl -ne 'next unless /Subject:/; s/.*CN=//; print')
echo "importing $ALIAS"
keytool -import \
-keystore $CACERTS_FILE \
-storepass changeit -noprompt \
-alias "$ALIAS" -file $CERT
done
cd "$OLDDIR"
echo "$NEWDIR"
Upvotes: 0
Reputation: 903
(repost from my other response)
Use cli utility keytool from java software distribution for import (and trust!) needed certificates
Sample:
From cli change dir to jre\bin
Check keystore (file found in jre\bin directory)
keytool -list -keystore ..\lib\security\cacerts
Password is changeit
Download and save all certificates in chain from needed server.
Add certificates (before need to remove "read-only" attribute on file ..\lib\security\cacerts
), run:
keytool -alias REPLACE_TO_ANY_UNIQ_NAME -import -keystore.\lib\security\cacerts -file "r:\root.crt"
accidentally I found such a simple tip. Other solutions require the use of InstallCert.Java and JDK
source: http://www.java-samples.com/showtutorial.php?tutorialid=210
Upvotes: 17
Reputation: 383
Here is the solution , follow the below link Step by Step :
JAVA FILE : which is missing from the blog
/*
* Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Sun Microsystems nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.io.*;
import java.net.URL;
import java.security.*;
import java.security.cert.*;
import javax.net.ssl.*;
public class InstallCert {
public static void main(String[] args) throws Exception {
String host;
int port;
char[] passphrase;
if ((args.length == 1) || (args.length == 2)) {
String[] c = args[0].split(":");
host = c[0];
port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
String p = (args.length == 1) ? "changeit" : args[1];
passphrase = p.toCharArray();
} else {
System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");
return;
}
File file = new File("jssecacerts");
if (file.isFile() == false) {
char SEP = File.separatorChar;
File dir = new File(System.getProperty("java.home") + SEP
+ "lib" + SEP + "security");
file = new File(dir, "jssecacerts");
if (file.isFile() == false) {
file = new File(dir, "cacerts");
}
}
System.out.println("Loading KeyStore " + file + "...");
InputStream in = new FileInputStream(file);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(in, passphrase);
in.close();
SSLContext context = SSLContext.getInstance("TLS");
TrustManagerFactory tmf =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
context.init(null, new TrustManager[] {tm}, null);
SSLSocketFactory factory = context.getSocketFactory();
System.out.println("Opening connection to " + host + ":" + port + "...");
SSLSocket socket = (SSLSocket)factory.createSocket(host, port);
socket.setSoTimeout(10000);
try {
System.out.println("Starting SSL handshake...");
socket.startHandshake();
socket.close();
System.out.println();
System.out.println("No errors, certificate is already trusted");
} catch (SSLException e) {
System.out.println();
e.printStackTrace(System.out);
}
X509Certificate[] chain = tm.chain;
if (chain == null) {
System.out.println("Could not obtain server certificate chain");
return;
}
BufferedReader reader =
new BufferedReader(new InputStreamReader(System.in));
System.out.println();
System.out.println("Server sent " + chain.length + " certificate(s):");
System.out.println();
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
MessageDigest md5 = MessageDigest.getInstance("MD5");
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = chain[i];
System.out.println
(" " + (i + 1) + " Subject " + cert.getSubjectDN());
System.out.println(" Issuer " + cert.getIssuerDN());
sha1.update(cert.getEncoded());
System.out.println(" sha1 " + toHexString(sha1.digest()));
md5.update(cert.getEncoded());
System.out.println(" md5 " + toHexString(md5.digest()));
System.out.println();
}
System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
String line = reader.readLine().trim();
int k;
try {
k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
} catch (NumberFormatException e) {
System.out.println("KeyStore not changed");
return;
}
X509Certificate cert = chain[k];
String alias = host + "-" + (k + 1);
ks.setCertificateEntry(alias, cert);
OutputStream out = new FileOutputStream("jssecacerts");
ks.store(out, passphrase);
out.close();
System.out.println();
System.out.println(cert);
System.out.println();
System.out.println
("Added certificate to keystore 'jssecacerts' using alias '"
+ alias + "'");
}
private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
private static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 3);
for (int b : bytes) {
b &= 0xff;
sb.append(HEXDIGITS[b >> 4]);
sb.append(HEXDIGITS[b & 15]);
sb.append(' ');
}
return sb.toString();
}
private static class SavingTrustManager implements X509TrustManager {
private final X509TrustManager tm;
private X509Certificate[] chain;
SavingTrustManager(X509TrustManager tm) {
this.tm = tm;
}
public X509Certificate[] getAcceptedIssuers() {
throw new UnsupportedOperationException();
}
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
throw new UnsupportedOperationException();
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
this.chain = chain;
tm.checkServerTrusted(chain, authType);
}
}
}
Upvotes: 31
Reputation: 4839
In my case I was facing the problem because in my tomcat process specific keystore was given using
-Djavax.net.ssl.trustStore=/pathtosomeselfsignedstore/truststore.jks
Wheras I was importing the certificate to the cacert of JRE/lib/security and the changes were not reflecting. Then I did below command where /tmp/cert1.test contains the certificate of the target server
keytool -import -trustcacerts -keystore /pathtosomeselfsignedstore/truststore.jks -storepass password123 -noprompt -alias rapidssl-myserver -file /tmp/cert1.test
We can double check if the certificate import is successful
keytool -list -v -keystore /pathtosomeselfsignedstore/truststore.jks
and see if your taget server is found against alias rapidssl-myserver
Upvotes: 0
Reputation: 383
I am working on a tutorial for REST web services at www.udemy.com (REST Java Web Services). The example in the tutorial said that in order to have SSL, we must have a folder called "trust_store" in my eclipse "client" project that should contain a "key store" file (we had a "client" project to call the service, and "service" project that contained the REST web service - 2 projects in the same eclipse workspace, one the client, the other the service). To keep things simple, they said to copy "keystore.jks" from the glassfish app server (glassfish\domains\domain1\config\keystore.jks) we are using and put it into this "trust_store" folder that they had me make in the client project. That seems to make sense: the self-signed certs in the server's key_store would correspond to the certs in the client trust_store. Now, doing this, I was getting the error that the original post mentions. I have googled this and read that the error is due to the "keystore.jks" file on the client not containing a trusted/signed certificate, that the certificate it finds is self-signed.
To keep things clear, let me say that as I understand it, the "keystore.jks" contains self-signed certs, and the "cacerts.jks" file contains CA certs (signed by the CA). The "keystore.jks" is the "keystore" and the "cacerts.jks" is the "trust store". As "Bruno", a commenter, says above, "keystore.jks" is local, and "cacerts.jks" is for remote clients.
So, I said to myself, hey, glassfish also has the "cacerts.jks" file, which is glassfish's trust_store file. cacerts.jsk is supposed to contain CA certificates. And apparently I need my trust_store folder to contain a key store file that has at least one CA certificate. So, I tried putting the "cacerts.jks" file in the "trust_store" folder I had made, on my client project, and changing the VM properties to point to "cacerts.jks" instead of "keystore.jks". That got rid of the error. I guess all it needed was a CA cert to work.
This may not be ideal for production, or even for development beyond just getting something to work. For instance you could probably use "keytool" command to add CA certs to the "keystore.jks" file in the client. But anyway hopefully this at least narrows down the possible scenarios that could be going on here to cause the error.
ALSO: my approach seemed to be useful for the client (server cert added to client trust_store), it looks like the comments above to resolve the original post are useful for the server (client cert added to server trust_store). Cheers.
Eclipse project setup:
Snippet from MyClientProject.java file:
static {
// Setup the trustStore location and password
System.setProperty("javax.net.ssl.trustStore","trust_store/cacerts.jks");
// comment out below line
System.setProperty("javax.net.ssl.trustStore","trust_store/keystore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
//System.setProperty("javax.net.debug", "all");
// for localhost testing only
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(new javax.net.ssl.HostnameVerifier() {
public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) {
return hostname.equals("localhost");
}
});
}
Upvotes: 4
Reputation: 22358
certs
root@c339504909345:/opt/jdk-minimal/jre/lib/security # keytool -cacerts -list
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 80 entries
root@c39596768075:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts # keytool -cacerts -list
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 151 entries
jlink
as /opt/jdk/bin/jlink \
--module-path /opt/jdk/jmods...
So, here's the different paths and the sequence of the commands...
# Java 8
COPY --from=marcellodesales-springboot-builder-jdk8 /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/cacerts /etc/ssl/certs/java/cacerts
# Java 10
RUN rm -f /opt/jdk-minimal/jre/lib/security/cacerts
RUN ln -s /etc/ssl/certs/java/cacerts /opt/jdk-minimal/jre/lib/security/cacerts
Upvotes: 5
Reputation: 41
Check if the file $JAVA_HOME/lib/security/cacerts
exists!
In my case it was not a file but a link to /etc/ssl/certs/java/cacerts
and also this was a link to itself (WHAT???) so due to it JVM can't find the file.
Solution:
Copy the real cacerts file (you can do it from another JDK) to /etc/ssl/certs/java/
directory and it'll solve your problem :)
Upvotes: 1
Reputation: 4250
My problem was that a Cloud Access Security Broker, NetSkope, was installed on my work laptop through a software update. This was altering the certificate chain and I was still not able to connect to the server through my java client after importing the entire chain to my cacerts keystore. I disabled NetSkope and was able to successfully connect.
Upvotes: 2
Reputation: 1273
I had the same problem with sbt.
It tried to fetch dependencies from repo1.maven.org over ssl
but said it was "unable to find valid certification path to requested target url".
so I followed this post
and still failed to verify a connection.
So I read about it and found that the root cert is not enough, as was suggested by the post,so -
the thing that worked for me was importing the intermediate CA certificates into the keystore.
I actually added all the certificates in the chain and it worked like a charm.
Upvotes: 8
Reputation: 2055
You need to configuring JSSE System Properties, specifically point to client certificate store.
Via command line:
java -Djavax.net.ssl.trustStore=truststores/client.ts com.progress.Client
or via Java code:
import java.util.Properties;
...
Properties systemProps = System.getProperties();
systemProps.put("javax.net.ssl.keyStorePassword","passwordForKeystore");
systemProps.put("javax.net.ssl.keyStore","pathToKeystore.ks");
systemProps.put("javax.net.ssl.trustStore", "pathToTruststore.ts");
systemProps.put("javax.net.ssl.trustStorePassword","passwordForTrustStore");
System.setProperties(systemProps);
...
For more refer to details on RedHat site.
Upvotes: 18