If you work on backend Java services long enough, you will eventually need to set up or debug TLS. The terminology — keystore, truststore, certificate, private key, CSR — can feel opaque until you understand the model.

This is my attempt to make that model clear.

What is a keystore?

A keystore is a file that holds private keys and certificates. Your application uses it to prove its own identity during a TLS handshake.

What is a truststore?

A truststore holds certificates of other parties you trust. When your application connects to another service over TLS, it checks whether that service's certificate is signed by a CA in your truststore.

The JDK ships with a default truststore at $JAVA_HOME/lib/security/cacerts that contains well-known public CAs.

The four-step setup

1. Generate private key
   keytool -genkeypair -alias myapp -keyalg RSA -keysize 2048 -keystore keystore.jks

2. Generate a CSR (Certificate Signing Request)
   keytool -certreq -alias myapp -file myapp.csr -keystore keystore.jks

3. Get the CSR signed by a CA
   (Submit myapp.csr to your CA — internal or public)

4. Import the signed certificate back into your keystore
   keytool -importcert -alias myapp -file myapp.crt -keystore keystore.jks

Self-signed vs CA-signed

Self-signed CA-signed
Cost Free Paid or Let's Encrypt
Trust Only if explicitly imported Trusted by default in most clients
Use case Internal services, dev Public-facing services

Why this matters at the senior level

Once you understand the model, a lot of operational problems become obvious: expired certificates (the CA signing chain changed), handshake failures (the other party's cert isn't in your truststore), and mutual TLS (both parties present certificates).

Most SSL errors in production are truststore problems, not keystore problems. Start there first.