I am trying to reach an external API through a secured connection. The connection usually requires a client certificate issued by the company. The certificate has been whitelisted and I also checked with Postman by importing the certificate and it worked fine. I am getting sun.security.validator.ValidatorException when I try to reach the API.
I generated these files using the .crt file:
trustStore.jks-
"C:\Program Files\Java\jdk1.8.0_341\bin\keytool" -import -file "C:/Users/user/certs/example.crt" -alias exampleCA -keystore "C:/Users/user/certs/truststore.jks"
2.keyStore.p12-
openssl pkcs12 -export -in "C:/Users/user/certs/example.crt" -inkey "C:/Users/user/certs/example.key" -certfile "C:/Users/user/certs/example.crt" -name "examplecert" -out "C:/Users/user/certs/keystore.p12"
3.keystore.jks-
"C:\Program Files\Java\jdk1.8.0_341\bin\keytool" -importkeystore -srckeystore "C:/Users/user/certs/keystore.p12" -srcstoretype pkcs12 -destkeystore "C:/Users/user/certs/keystore.jks" -deststoretype JKS
I have the keyStore setup in properties:
server.port=443
server.use-forwarded-headers=true
security.require-ssl=true
server.ssl.key-store-type=PKCS12
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password= password
server.ssl.key-alias=examplecert
When I hit the url, I can see the same cert being used with httpsnot-secure error
However, when I click in the background 'thisisunsafe' as mentioned here stackoverflow-answer, I get the error:
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is 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] with root cause
Can someone help me in this? I am completely new to SpringBoot.
Related
I'm trying to send a request with HttpsURLConnection to an endpoint with a custom SSL certificate but I am still getting PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target.
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(
utilService
.getCertificate(
item.getCertificatePath(), item.getCertificatePassword())
.getSocketFactory());
I have the certificates as files in the project, and I add them manually to the connection. The problem is that this works with some of the other websites I need, but there's one that still is throwing a 403 error.
I tried adding the certificate to the Java Keystore but the error still persists:
COPY /src/main/resources/transport.crt /home/transport.crt
RUN $JAVA_HOME/bin/keytool -import -file /home/transport.crt -alias certificate1 -keystore "/opt/openjdk-17/lib/security/cacerts" -trustcacerts -storepass changeit -noprompt
I don't really understand why adding the certificate manually to the connection doesn't work, nor why doesn't it work when I add it to the key store.
I'm reviewing a training project - working with a mail server gmail.com. An error occurred at startup:
Failed receive: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
On this site I found instructions on how to connect the certificate: PKIX path building failed” and “unable to find valid certification path to requested target
I'm reviewing a training project - working with a mail server gmail.com. An error occurred at startup:
Failed receive: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
On this site I found instructions on how to connect the certificate: PKIX path building failed” and " unable to find valid certification path to requested target
I did everything according to the instructions:
In chrome, I downloaded the certificate from this site, saved it to the mg mail.cer file
I connected it with the command
keytool -import -alias gmail -keystore c:\Development\Java\jdk11\lib\security\cacerts -file m gmail.com
I overloaded the computer, but the error still remains
I check with the command
keytool -list -trustcacerts -keystore "%JAVA_HOME%\lib\security\cacerts" -storepass changeit
the certificate is in the list:
mgmail, 2 февр. 2021 г., trustedCertEntry,
Certificate fingerprint (SHA-256): 9A:63:32:BE:95:...
What did I miss?
According to this error, It seems like you haven't imported the full cert chain to the trust store (root, intermediate and leaf certs).
enter image description here
In Firefox, You can easily download the full certificate chain. Then please import all 3 certificates to your trust store.
I have one GET API to call using java and I have used feign client to call this API.
When I call this API it is giving the error:
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
at java.base/sun.security.validator.Validator.validate(Validator.java:264)
at java.base/sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:313)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:222)
at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:129)
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1323)
... 18 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
When I hit the same API in the browser, it is working fine. Browser doesn't display like an untrusted connection.
certificate information from firefox:
I am running my application in docker image openjdk:11-slim.
Why java is not able to validate the certificate even if the certificate is valid?
This may be because they are not added to your cacerts -
You can try running installCerts from below link, for the URL of site which you are trying to downlaod certificate from or which is not being allowed to access because of certificate issue.
java --source 11 InstallCert.java
https://github.com/escline/InstallCert
If it is self signed certificate, try below in your DockerFile -
FROM openjdk:11-jdk-slim
WORKDIR /opt/workdir/
#.crt file in the same folder as your Dockerfile
ARG CERT="certificate.crt"
#import cert into java
COPY $CERT /opt/workdir/
RUN keytool -importcert -file $CERT -alias $CERT -cacerts -storepass changeit -noprompt
If you have the .cer file, which you can otherwise export from browser. Add below to your DockerFile. So the required certs are available before ssl handshake. -
ADD your_ca_root.crt /usr/local/share/ca-certificates/foo.crt
RUN chmod 644 /usr/local/share/ca-certificates/foo.crt && update-ca-certificates
Into my application I'm using an HttpClient setting an ssl context:
#Bean
public HttpClient httpClient() throws Exception {
SSLContext sslContext = SSLContextBuilder.create()
.loadKeyMaterial(
new URL(schedulerConfiguration.getKeyStore()),
schedulerConfiguration.getKeyStorePassword().toCharArray(),
schedulerConfiguration.getKeyPassword().toCharArray()
)
.loadTrustMaterial(
new URL(schedulerConfiguration.getTrustStore()),
schedulerConfiguration.getTrustStorePassword().toCharArray()
)
.build();
return HttpClients.custom().setSSLContext(sslContext).build();
}
As you can see I'm loading a keystore and a truststore.
keystore contains the private key and truststore contains all chain certificates.
I'm running against client connections can't be launched due to:
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://balancer:8080/token": sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is 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
Caused by: 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
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I've built my jks from a .p12 file like this.
In order to build trsutstore:
$ openssl pkcs12 -in fitxers.p12 -nokeys -out cacerts-nokeys.crt
$ keytool -importcert -file cacerts-nokeys.crt -keystore cacerts-pre-splitted.jks
And in order to create my keystore:
$ keytool -importkeystore -srckeystore fitxers.p12 -srcstoretype pkcs12 -destkeystore auth-backoffice-pre.jks -deststoretype jks
Any ideas about what's wrong?
I remember having similar issue when not using aliases properly. Are you using aliases in your original p12 file? If so, I'd recommend using the other method for loading the key material with custom PrivateKeyStrategy.
Also take a look when trying to connect your client with vm option:
-Djavax.net.debug=all
You will be able to see a bit of more information. Hopefully this guides you to your solution!
I have Created CSR request using this command :
openssl req -out certificatecsr.csr -new -newkey rsa:2048 -keyout certificatekey.key
After that CA has shared certificate(.cer) file with me.
Now after that i have converted .cer file to .p12 using key.
Creating a .p12 certificate using cer sent by CA and private key
C:\Java\jdk1.6.0_38\jre\bin>openssl pkcs12 -export -in C:\Users\asharma1\cert.cer -inkey certificatekey.key -out
certi.p12
Creating JKS keystore :
keytool -genkey -alias quid -keystore quid.jks
importing .p12 certificate into jks keystore
C:\Java\jdk1.6.0_38\jre\bin>keytool -v -importkeystore -srckeystore C:\OpenSSL-Win64\bin\certi.p12 -srcstoretype PKCS12
-destkeystore quid.jks -deststoretype JKS
but when i am referring this JKS from my java code i am getting this error :
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I have also added cer file to cacerts.but still getting the same error.
As far as JAVA code is concerned i am refering this link to refer my own created keystore :
http://jcalcote.wordpress.com/2010/06/22/managing-a-dynamic-java-trust-store/
public SSLContext getSSLContext(String tspath)
throws Exception {
TrustManager[] trustManagers = new TrustManager[] {
new ReloadableX509TrustManager(tspath)
};
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagers, null);
return sslContext;
}
SSLContext sslContext=getSSLContext("C:\\Java\\jdk1.6.0_38\\jre\\bin\\quid.jks");
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
URL pickUrl = new URL(pickupLocation);
URLConnection urlConn = pickUrl.openConnection();
HttpsURLConnection httpsURLConn = (HttpsURLConnection)urlConn;
httpsURLConn.setSSLSocketFactory(socketFactory);
String encoding = urlConn.getContentEncoding();
InputStream is = urlConn.getInputStream();
InputStreamReader streamReader = new InputStreamReader(is, encoding != null
? encoding : "UTF-8");
Please note i am not using any server. I am trying ti run above written code thorugh main method only.
Please let me know what need to be done.
Why do i need to convert my .cer file to .p12 file ?
I would suggest you import CA certificate (or whole chain of CA and intermediate CAs) to keystore.
I think that p12 was imported fine. What I am suggesting is import of the chain to keystore. At least that is what the error message is saying.
I presume that:
the root CA in the chain is not trusted so chain building fails or
there is no AIA section in certificates in the chain so no certificates up to trusted root CA can be fetched so chain building fails or
the certificates are not being fetched based on AIA because it is not implemented in java (I am not a java programmer) so chain building fails
You could use portecle to import missing trusted CA certificates (not end entity cartificate that you have in .p12 or in separate .cer file that you received from issuing CA). It is more user friendly than keytool. Just follow this guide.
I would suggest you use the *.der format instead of the .p12 format.
Here's an overall summary of how to import certificates to fix the following error:
Error while trying to execute request.
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
How to import certificates
Go to URL in your browser, click on HTTPS certificate chain (little lock symbol next to URL address) to export the certificate
Click "more info" > "security" > "show certificate" > "details" > "export..".
Save as .der
Repeat for any certificates you need to import
Locate $JAVA_HOME/jre/lib/security/cacerts
Import all *.der files into the cacerts file using the following:
sudo keytool -import -alias mysitestaging -keystore $JAVA_HOME/jre/lib/security/cacerts -file staging.der
sudo keytool -import -alias mysiteprod -keystore $JAVA_HOME/jre/lib/security/cacerts -file prod.der
sudo keytool -import -alias mysitedev -keystore $JAVA_HOME/jre/lib/security/cacerts -file dev.der
The default keystore password is 'changeit'
You can view the change that you made with this command that shows the Certificate fingerprint.
keytool -list -keystore $JAVA_HOME/jre/lib/security/cacerts
If this doesn't solve the problem, try adding these java options as arguments:
-Djavax.net.ssl.trustStore="$JAVA_HOME/jre/lib/security/cacerts"
-Djavax.net.ssl.trustStorePassword="changeit"