SSLHandshakeException: PKIX path building failed with Unable to find certificate chain - java

I am trying to Connect SSRS ReportServer with HTTPS Protocol from Java Client it's giving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: java.security.cert.CertPathBuilderException: Unable to find certificate chain
But I have added the certificate in Java Keystore, It the keystore the certificate is showing with the defined alias name.
But Same SSRS Request call is working with HTTP Protocol.
Note: We are using a wildcard certificate from Go-Daddy for secure communication

Can you verify that the certificate is added to 'Java Truststore' and not Keystore (although both have .jks extension).
Have a look at this https://docs.oracle.com/cd/E19830-01/819-4712/ablqw/index.html
Keystore file, keystore.jks, contains the Application Server’s certificate, including its private key
Truststore file, cacerts.jks, contains the Application Server’s trusted certificates

When you got your certificate, there should have been a p7b (possibly) included with it.
Essentially, when GoDaddy issues a certificate, they are not issued from the root directly.
Most likely you have one issued from an intermediate authority.
You can get the intermediate certificates at https://ssl-ccp.godaddy.com/repository?origin=CALLISTO
The certificate chain needs to be appended to the actual certificate and imported on the server.
The PEM file containing the cert being imported should look like:
<actual certificate>
<intermediate certificate>
[<intermediate certificate> ...]
After that you shouldn't have a need to do anything else on the client.
EDIT
After re-reading my answer, I realized there may be a little bit of vagueness with regard to the process. So in efforts to bring this more full cycle here we go.
Generate keypair / self-signed certificate as say PKCS#12 container.
Create PKCS#10 certificate signing request to send to GoDaddy of above certificate.
GoDaddy returns signed X.509 Certificate (typically with instructions on how to install it).
Taking the certificate (assuming PEM format) and concatenate the issuance chain from https://ssl-ccp.godaddy.com/repository?origin=CALLISTO and import that back into the PKCS#12 from step 1.
Assign the PKCS#12 as the TLS certificate store on the SSRS server.

Related

Wildfly does not pass intermediate certificate to HTTPS client

So I have this certificate chain made of 3 certificates:
Root cert (installed in all clients)
Intermediate cert (installed in my browser, but not in other clients/Java apps accessing webservices)
Domain wildcard certificate
Wildfly is configured to use a keystore that holds intermediate and domain certificates in JKS format, along with the private key for the domain cert. When I send a HTTPS request from my browser, the certificate is validated just fine and everything seems OK. But when the Java client application I am working on tries to establish a connection, it cannot build a valid certificate chain:
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I checked the certificates delivered by Wildfly using openssl (openssl s_client -showcerts -connect <servername>) and confirmed that the intermediate certificate is NOT transmitted even though it is present in the keystore. Now I can work around this in my development environment by adding the intermediate cert to my local trust store, however that is not an acceptable long-term solution for production.
In my Wildfly's standalone.xml I have specified the keystore and the alias of the wildcard certificate.
<server-identities>
<ssl>
<keystore path="/path/to/keytsore.jks" keystore-password="supersecure" alias="*.redacted.com"/>
</ssl>
</server-identities>
Searching through the Wildfly admin docs I saw no mention of intermediate certificates. I tried to add an additional element to the config (same path and password, but alias of the intermediate certificate), but Wildfly would not start up with that.
Any idea how I can get Wildfly to present the intermediate certificate to connecting clients? Does it need to have a specific alias name? Or is there another way to tell Wildfly the alias of any intermediate cert?

certificate mechanism between webservice provider and consumer

What are the exact steps done by server and client to place a ssl certificate mechanism in a webservice call? Who(client/server/both) will generate .keystore,.p7b/.cer files? I have googled a lot but couldn't find the answer to it.
In my case, i am the client running a java application which consumes a soap webservice call. I have a .p7b file given by WebService provider. I know where to place the files(.keystore, .cer) and how to use it in the application.
But, my questions are
Do i need to generate keystore file or should i get it from
webservice provider? If i need to generate, how? Do i need private
key/passphrase?
I need a .cer file, so how can i use keytool to convert .p7b to .cer
file?
Thank you for your help in advance.
It looks like you're calling a web service where the HTTP connection is protected by TLS/SSL using X509 certificates. That means the server has set up a keystore with those certificates as well as the corresponding private keys. When you call the web service, the server will retrieve from its keystore the certificate used for the trust establishment (that is, to protect the TLS connection to the web service) and sends it to the client. When the client receives the response from the server it will check the trust of that certificate. Now we have two scenarios:
If the server uses a self-signed certificate (can be used for developments and testing, but not in production), then the client won't recognize it as trusted because it's not stored in the client's truststore. By default, in a Java environment, the truststore is searched (by order) in the following two locations: $JAVA_HOME/lib/security/jssecacerts and $JAVA_HOME/lib/security/cacerts. A custom truststore can also be used by running the client with -Djavax.net.ssl.trustStore and -Djavax.net.ssl.trustStorePassword or by using a custom TrustManager. As such, if the server self-signed certificate is not stored in one of these locations, the secure connection will fail. So the client will have to import the certificate into its truststore. To circumvent the import of self-signed certificates into the client's truststore, you can create a custom X509TrustManager as stated here.
If the server uses a certificate signed by one of the recognized root CA authorities, then it'll be validated automagically because those CA's certificates are already installed in Java's default truststore. As such, the trusted TLS connection will be successful.
In the case where the server does not require client authentication the process is over (this is what happens when you connect to most HTTPS websites via browser).
If the server requires client authentication, then the client will need to provide its own certificate from its keystore to the server, and the server will need to have it installed in its truststore. The web service provider must provide to the client the specification for the certificate profile that the client should use.
Here you can find a good clarification to the keystore vs truststore terminology.
By default in Java environments, keystores and truststores are JKS files.
So you're saying you have a .p7b file provided by the web service provider. Quoting from this page:
PKCS#7/P7B Format
The PKCS#7 or P7B format is usually stored in Base64 ASCII format and has a file extention of .p7b or .p7c. P7B certificates contain "-----BEGIN PKCS7-----" and "-----END PKCS7-----" statements. A P7B file only contains certificates and chain certificates, not the private key. Several platforms support P7B files including Microsoft Windows and Java Tomcat.
So that P7B file contains the server certificate or certificate chain (more on this here).
I believe you're in a no-client-auth scenario. Therefore, you won't need your own keystore. You'll only need to import the server's certificate (P7B file) into the truststore you're using. You can directly import a P7B file without converting it to CER format:
keytool -import -trustcacerts -alias web_service -keystore my_truststore.jks -file web_service.p7b
In the case you still want a CER formatted certificate, you can convert from P7B to CER like this (to answer to your 2nd question):
openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
If in fact client authentication is needed, then you'll need to create your keystore with your private key and public certificate and provide it to the connection by either the -Djavax.net.ssl.keyStore and -Djavax.net.ssl.keyStorePassword parameters or through a KeyManager. The same workflow previously explained applies now in the opposite direction.

Converted PFX SSL cert throwing SSLHandshakeException?

I was given a PFX "wildcard" SSL certificate (I believe its a VeriSign cert) for *.ourdomain.example.org. I then used this answer to help me convert the PFX into a JKS keystore entry and add it to a JKS keystore. When I run keytool -list -keystore mykeys.jks I see:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
<my key's long GUUID>, May 1, 2014, PrivateKeyEntry,
Certificate fingerprint (SHA1): <cert's fingerprint>
So I know the converted PFX cert is in there. But at runtime, when JNDI is using SSL to establish a connection to my AD server (over LDAPS), I am seeing the following exception:
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'm wondering if something got botched in the conversion from PFX to JKS. I'm pretty sure nothing else is wrong with the SSL cert, because I was using a self-signed cert before using this PFX and my browser was giving me the typical "I do not trust this certificate" warning. After I added the converted PFX and restarted my app, those warnings went away. Any ideas as to what could be going on here?
Firstly, in many cases, you don't need to convert from PKCS#12 (PFX) to JKS, many applications will let you set the keystore type to PKCS12 (instead of the default JKS), which will allow you to use your PFX file directly.
It looks like you're mixing up the usage of trust store and key store here (see this question).
Having a keystore with a certificate and its PrivateKeyEntry (here, coming from a PKCS#12 file) is normally used as a "keystore keystore" (as opposed to a keystore used as a truststore). This would normally be used for the certificate you present to your clients as a server, or the client certificate you use when connecting to a server that requests one.
Here, the "PKIX path building failed" exceptions means that your Java application doesn't trust the remote certificate it is connecting to. Presumably, your AD server has nothing to do with this JKS keystore. Rather, your server that uses your keystore is also a client to that AD server, and it cannot trust the AD server certificate.
You don't say how you've configured your application. Perhaps you've used your keystore for both the keystore and truststore settings (effectively preventing the use of the CA certificates bundled with the default JRE truststore), or perhaps your AD certificate is self-signed or not issued by a CA that is part of the default truststore. If the latter is the case, simply import the AD certificate (just the certificate, not the certificate and its private key) into the trust store (you can either do this into the JRE's cacert file or make a copy of it and use that using the javax.net.ssl.trustStore and related system properties).

How to add fingerprint to keystore

I had the following exception while writing to a SSL socket
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Path does not chain with any of the trust anchors
It seems like the certificate of the target server is not trusted. I tested my implementation on a windows 7 machine, jdk7 and tomcat7 with no problem. The Exception is thrown on ubuntu 10 LTS with openJDK 6 and tomcat7. I got the sha1 and md5 fingerprint of the sockets target server. Am I right that the certificat of the server I am trying to stream to is not trustet on my ubuntu server? can I can the fingerprint to the tomcats keystore? If so, how do I do this?
It's not the fingerprint that you need to add to your trust store, but the actual certificate.
You can add the server certificate itself or add one of the CA certificates in the chain (if you wish to trust the all the certificates from that CA, not just that particular server).
To find out what the certificate is, you can use OpenSSL:
openssl s_client -showcerts -connect your.host.name:443
(Replace the host name and 443 by the actual ports you're using.)
The blocks between --BEGIN/END CERT...-- are the certificates in PEM format. You can check their content using openssl x509 -text -noout (and pasting each block there).
Save the certificate you want to import into a plain text file (e.g. certificate.pem). You should only import certificates that you trust. There's a certain leap of faith here. (You might want to connect with your browser and check whether the key material matches, for example.)
To import into your truststore use:
keytool -importcert -keystore truststore.jks -file certificate.pem
(You may need to specify an alias wit -alias some_name_you_choose.)
If you want this to affect your default truststore, replace truststore.jks with the path to lib/security/cacerts in your Java home directory (the default password should be changeit).
Since the target server seems to come from a well-known CA anyway (and it works with some versions of the JRE), the easiest fix is certainly to update your cacerts file manually, taking a copy from a JRE with which it works. After all, as the JSSE Reference Guide says:
IMPORTANT NOTE: The JDK ships with a limited number of trusted root
certificates in the /lib/security/cacerts file. As
documented in keytool, it is your responsibility to maintain (that is,
add/remove) the certificates contained in this file if you use this
file as a truststore.
Depending on the certificate configuration of the servers you contact,
you may need to add additional root certificate(s). Obtain the needed
specific root certificate(s) from the appropriate vendor.
It turns out it's certainly a problem with the certificate chain order (which is incorrect on this site), as shown by Qualys SSL Labs tester.

Using HttpClient with SSL and certificates

While I've been familiar with HTTPS and the concept of SSL, I have recently begun some development and found I am a little confused.
The requirement was that I write a small Java application that runs on a machine attached to a scanner. When a document is scanned this is picked up and the file (usually PDF) sent over the internet to our application server that will then process it. I've written the application using Apache Commons libraries and HTTPClient.
The second requirement was to connect over SSL, requiring a certificate. Following guidance on the HTTPclient page I am using AuthSSLProtocolSocketFactory from the contributions page.
The constructor can take a keystore, keystore password, truststore and truststore password. As an initial test our DBA enabled SSL on one of our development webservers and provided me with a .p12 file which when I imported into IE allows me to connect successfully.
I am a bit confused between keystores and truststores and what steps I need to take using the keytool. I tried importing the p12 into a keystore file but get the error:
keytool error: java.lang.Exception: Input not an X.509 certificate
I followed a suggestion of importing the p12 into Internet Explorer and exporting as a .cer which I can then successfully import into a keystore. When I supply this as a keystore argument of the AuthSSLProtocolSocketFactory I get a meaningless errror, but if I try it as a truststore it seems like it reads it fine but ultimately I get
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
I am unsure if I have missed some steps, I am misunderstanding SSL and mutual authentication altogether or this is mis-configuration on the server side.
Can anyone provide suggestions or point me towards resources that might help me figure this out please?
The keystore holds your private keys and associated certificates. The truststore hold the certificates that you trust and that can therefore be used for certificate path building and verification.
Here are some links that may be useful:
java.lang.Exception: Input not an X.509 certificate
Import private key and certificate into Java Key Store
Configuring Keystores and Truststores
make sure your certificate file does not have anything before and after these.
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----

Categories