How can I inspect a HTTPS certificate before making a connection - java

I'm trying, in java, to connect to a HTTPS endpoint. The server's certificate is signed by an internal CA. (not included in the truststore). Because of that, connection fails as expected
How can I inspect a certificate from a https server before the connection is made (in java). I need to view it to know what CA certificate I need to import.
I can do this using openssl like so
openssl s_client -connect www.paypal.com:443
But I would like to do this from Java
Thanks!

You do a connection with disabled chain verfication.
You could find an example there:
http://www.nakov.com/blog/2009/07/16/disable-certificate-validation-in-java-ssl-connections/
After having the insecure connection you could inspect the certificate

Related

Spark app not sending intermediate / chain certificates

I've got an app written using the Spark Java framework, with TLS enabled.
See:
Service https = ignite()
.port(8443)
.secure(keystorePath, keystorePass, truststorePath, truststorePass);
This is being served on port 443 via an iptables rule that redirects incoming 443 to 8443.
The problem I am having is that when using the Qualys ssl labs test (https://www.ssllabs.com/ssltest/) the server is not providing the intermediate certificates that have been configured in my truststore.
Similar results occur when I use openssl s_client:
Verify return code: 21 (unable to verify the first certificate)
Along with
depth=0 /OU=Domain Control Validated/OU=PositiveSSL/CN=my.app.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /OU=Domain Control Validated/OU=PositiveSSL/CN=my.app.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 /OU=Domain Control Validated/OU=PositiveSSL/CN=my.app.com
verify error:num=21:unable to verify the first certificate
verify return:1
From what I can tell, it appears that the server (spark java app, or embedded Jetty I suppose) is not serving up the intermediate certificates for chain validation.
Browsers see the site as secure, but I believe that's because the browsers are downloading the necessary intermediate certificates on their own.
The reason that this is a problem is that I am trying to use Stripe payment webhooks, and they have strict regulations in terms of the TLS cert chain being valid.
I am not sure where to begin on figuring out why these intermediate certs are not being served by my app. Could anyone offer some advice?
I have more or less the same exact problem. I followed the instructions at the Java Spark website (sparse that they are) and only get a Server Error for my efforts.
I imported a third-party certificate in my keystore file. I generated the CSR externally to the java keytool.
I moved the keystone file on the server where the "mydomain.com" exists.
I have the same basic code to do a test "secureHello" (per their documentation), passing the path to the keystore.jks file as the first parameter, and the password as the second.
RESULT: SERVER ERROR.
Not sure what I can try next. Clearly, I'm missing something.
4 hours banging my head on the desk so far (today)...

hitting javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated even imported cert

Good day,
As my understanding, if an application needs to connect to a https web service, I have to download the cert from the URL and import the cert to WAS Console. This is working fine for me.
Until today, the application has to call a new https URL. Same way, I download the cert and import the cert into WAS Console, but application hitting peer not authenticated error.
After my checking, this URL is using CA cert, not the self-sign cert that I imported usually. May I know is it the way to import CA cert into WAS Console different?
Based on the screen shot below, I imported total 3 cents.
Am I doing the correct way? or for CA cert URL, I need to ask cert from the URL owner? instead of downloading myself.
Will it be caused by protocol issue? I already set the WAS setting protocol to SSL_TLSv2
Kindly advise.
WebSphere has a "retrieve signer from port" function in the SSL Certificate Management UI. That will connect to the host/port you instruct it to and find the root, self-signed issuer (if the server sends it, it's not required) and add it as trusted.
If the server does not send its root, self-signed issuer, you can always look at the last certificate it provides in the chain and add it manually.

Behavior of HttpsURLConnectioin with default implementation of HostnameVerifier and SSLSocketFactory

I am trying to understand a piece of code that does not override HostnameVerifier and SSLSocketFactory for HttpsURLConnection. The current code is able to make the SSL request fine, which is a little confusing to me.
How does the default implementation of HostnameVerifier and SSLSocketFactory classes work? Does it verify the certificate CA and hostname or it bypasses all these checks all together?
Also, is there any special behavior if the request has localhost in it?
The URL looks like this
https://localhost:/
Thanks for your help.
It will check the CA certificate against the trusted ca-certificates in the trusted store of the JDK jre/lib/security/cacerts or whatever you have configured.
It will also check, that all certificates in the chain are trusted, not only the immediate signer. It will, by default, not check online for revoked certificates, but you can enable that in the java.security policy file.
It will also check the hostname against the certificate.
It supports additional CNs and wildcard CNs.
Extended question regarding localhost:
localhost is just a hostname like any other. It must be listed in the certificate. But you will not find an official CA to give you that certificate, I guess :-)
If you want to play with your real cert on localhost, you address it with a different hostname. If you want to run through a cert for foo.bar.com, add to your hosts file (Win: %WINDOWS%\system32\drivers\etc\hosts, Unix /etc/hosts) the line:
127.0.0.1 foo.bar.com
Now fire up your browser and connect to https://foo.bar.com. It will connect to your local server and post a SSL encrypted HTTP request. That request contains the hostname from the URL, not the real hostname.
I was oversimplyfying: The browser receives the SSL certificate from the server and compares the CN against the hostname it just called. If this matches, it will check if the certificate can be trusted (don't nail me down on the order, maybe it will check the trustlevel first).
Here is where you fail: The certificate provided by the server does not contain the CN localhost, and thus, the client will abort the connection. In your case, the client is the HttpSSLrequest.
To make the client believe all is well, you can do two things:
- fake the hostname, and add the signing CA in the cacerts truststore.
- implement a hostname and certificate validator, that lets you through.
Regarding the tutorial, a self-signed certificate is used, you will have to convince the browser to accept it by overriding the warning on first access.

ssl certificate error: unable to get local issuer certificate

This website, https://dcs1.noaa.gov, recently updated their SSL certification. Since that change I cannot grab a file from there that I need. I get the following error:
--08:37:12-- https://dcs1.noaa.gov/pdts_compressed.txt
=> `pdts_compressed.txt'
Resolving dcs1.noaa.gov... 205.156.2.181
Connecting to dcs1.noaa.gov|205.156.2.181|:443... connected.
ERROR: Certificate verification error for dcs1.noaa.gov: unable to get local issuer certificate
To connect to dcs1.noaa.gov insecurely, use `--no-check-certificate'.
Unable to establish SSL connection.
I am running Red Hat Linux 4.x and updated all the openssl packages. The usual process I use to access this file is running in Java and uses URL.openStream() to read the file. The command wget also does not work so I am assuming that it is an SSL problem and not a java problem.
the cert is issued by Verisign, probably their root cert is in your servers root cert store. Open the webpage from your machine from a browser and you will see the cert is valid. You can also try to wget from another machine and it will work too.
Probably, the new server certificate is issued by an issuing authority that is not trusted by you. You need to import the issuing authority's certificate in your truststore.
You could try testing the SSL connection with openssl's s_client. I recently had a similar problem and had it resolved. Here's a link to that solution. It also includes information on how to use the s_client to test an SSL connection.
SSL Error: unable to get local issuer certificate

Java certificate based authentication

I have a thrift endpoint that someone created who is not longer with our company. They implemented the authentication via client side certs, but I having a hard time wrapping my head around how it all works. Does anyone know of a tutorial, or howto on this topic.
All I really have is a sample client class. Here are a list of things that I need help with:
Can a server cert and the client cert both be contained in the same trust store
How do you create a new client side cert?
How do you add that client side cert to the server trust store?
Do you need to set the client trust store, and set the java trust (assuming the server is a self signed endpoint)
What does the following error mean?
ERROR[com.cada.CadaDaoTest][main] - Error:
org.apache.thrift.transport.TTransportException: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate
The truststore (on Tomcat it's configured forthe SSL connector in server.xml) can hold the root of the certificate chain of the client certificate, not the certificate itself. That is, when a certificate is created, it is signed by a CA - certificate authority. If the CA cert is trusted, all certs singed by the CA are trusted as well.
You can create certificates using either keytool (in jdk/bin/) or openssl. There are GUIs for that, like portecle.
The tomcat ssl tutorial might be helpful.

Categories

Resources