I work with a Java client and server that our startup recently acquired with very limited access to devs who built it. There is very limited documentation. It seems that the Java client used to connect to their server with TLS, there is an Nginx server rule for the right endpoint and a cert and private key associated with it. However, the developer claims that they did not need to have a public key present on the machine that runs the Java client.

So far I learnt that Java stores these trusted certs in the jre/lib/security/cacerts file. After installing a self-signed cert in there I was able to make the Java client connect to the server with encryption.

Now the question is: how does the cert become available to Java? Does it have to be installed each time manually into cacerts? Or will it become available to Java after we get a legit cert from some authority like Thawte? By "become available" I mean, will Java's HTTP lib go and find that cert with the public key authority? (I am not familiar with how cert verification works with non-browser clients.)

I am told by the dev of the Java client and server that the public key is downloaded from the server itself during the connection, which to me does not make sense and kind of defeats the purpose of security - if both public key and private key come from the same source, how can we trust it?

I am learning a lot of it as I go (it's a startup) and only know public crypto in theory from the university, but in practice it looks a little different. :) Thank you.


2 Answers 2


A trusted certificate is signed (please read all the answer in the link) by an intermediate certificate which is itself signed by a root certificate. There might be more than one intermediate in the chain, one after another. The root certificate is distributed by Oracle (and also probably by Microsoft and Apple in OS updates and by Linux distros in the certificates package based on Mozilla's root program).

During the TLS handshake, the TLS server sends the leaf certificate and all the intermediates to the TLS client. The TLS client verifies all the digital signatures (the handshake is signed by the key in the leaf certificate, that is signed by the key for the intermediate, etc.) up to the root certificate which is trusted implicitly, not because of cryptography but because someone put that root certificate file in the right directory.

There is no directory of certificates or public keys for domains, the server hands you a certificate. There is a project called Certificate Transparency started by google to achieve a public log of all publicly trusted certificates for all publicly reachable servers, but it's not meant to be used for establishing TLS connections, though a proof that the certificate has been logged is required by browsers for EV certificates and certificates issued by CAs owned by Symantec and in 2017 Google plans to require proof of logging for all certificates.

The CA does not need to be contacted to verify the certificate.

If you want to check that the certificate has not been revoked, the TLS client needs to either contact the CA's CRL or get a stapled OCSP response from the TLS server. Certificates can be set up (at creation) to say "don't trust this certificate without checking revocation", this is called "OCSP Must Staple". I don't know whether your client even tries to check for revocation - many don't.

Untrusted certificates can be just like trusted ones but signed by a CA whose root is not trusted by your client. Many organization run their own internal CA which is trusted by all their clients (IT adds the CAs root to all computers) and this CA is used to issue certificates for their internal servers. The CA might also issue SSH and VPN certificates. For a TLS client not familiar with the internal CA, a certificate issued by one would be untrusted.

Untrusted certificates can also be self-signed. To validate such a certificate, the client must have, before making a connection, a copy of the certificate itself, not of any root, which it acquired "out of band" (i.e. a developer copy-pasted it). I would recommend passing it (the hardcoded self-signed certificate) to the API making the network connection instead of making it a trusted root certificate for the computer on which the client software is installed.


Once you get a "legitimate" certificate java will trust that certificate natively. Java ships with a list of standard CAs (much as your browser does) and will be able to chain that together.

There are many things that can go wrong - if it doesn't work, you need to make sure:

  • The server is configured correctly (sends the certificate and intermediate certificates that chain up to the CA)
  • The CA is in the java trust store (cacerts)
  • The client is is coded to use the default java trust store - leveraging the java URL class is usually the simplest way to do that

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .