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.
- The private key never leaves your machine.
- The certificate is the public-facing document that proves your identity. You share this.
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.