keytool — quick reference
Key pairs and local certificates
Create the private key and an initial certificate inside a keystore — the usual first step before a CA signs your CSR.
| When to use | Command |
|---|---|
| Generate an RSA key pair and self-signed cert in a new PKCS12 keystore | keytool -genkeypair -alias NAME -keyalg RSA -keysize 2048 -validity 365 -storetype PKCS12 -keystore store.p12 -storepass PASS -dname "CN=host" -noprompt |
| Add a Subject Alternative Name at creation time | keytool -genkeypair … -ext "SAN=dns:localhost,ip:127.0.0.1" |
| Use an EC key instead of RSA | keytool -genkeypair -alias NAME -keyalg EC -groupname secp256r1 -keystore store.p12 -storepass PASS -dname "CN=host" -noprompt |
| Set a separate key password (JKS; PKCS12 uses one store password) | keytool -genkeypair … -keypass KEYPASS |
Certificate requests and CA signing
Build a CSR from an existing key entry, then replace the self-signed cert with a CA reply.
| When to use | Command |
|---|---|
| Generate a CSR for an existing alias | keytool -certreq -alias NAME -file host.csr -keystore store.p12 -storepass PASS |
| Add SAN extensions on the CSR | keytool -certreq -alias NAME -file host.csr -keystore store.p12 -storepass PASS -ext "SAN=dns:app.example.com,ip:10.0.0.5" |
| Sign a CSR with a CA key already in the same keystore | keytool -gencert -alias CA_ALIAS -infile host.csr -outfile host.crt -rfc |
| Show CSR contents without importing | keytool -printcertreq -file host.csr |
Import certificates and keystores
Bring external certs or whole keystores into Java stores.
| When to use | Command |
|---|---|
| Import a CA or server certificate file | keytool -importcert -alias NAME -file cert.pem -keystore store.p12 -storepass PASS -noprompt |
| Install a CA-signed reply over the CSR alias (replaces chain) | keytool -importcert -alias NAME -file signed.crt -keystore store.p12 -storepass PASS -noprompt |
Trust CA certs from the JDK cacerts while building a chain |
keytool -importcert -alias NAME -file reply.crt -keystore store.p12 -storepass PASS -trustcacerts -noprompt |
| Copy one entry from another keystore | keytool -importkeystore -srckeystore src.p12 -srcstoretype PKCS12 -srcstorepass PASS -destkeystore dest.p12 -deststoretype PKCS12 -deststorepass PASS -srcalias SRC -destalias DST -noprompt |
| Merge all entries from a source keystore | keytool -importkeystore -srckeystore src.p12 -srcstorepass PASS -destkeystore dest.p12 -deststorepass PASS -noprompt |
| Import a public CA into the system truststore (needs sudo) | sudo keytool -importcert -alias NAME -file ca.crt -cacerts -storepass changeit -noprompt |
Export, list, and inspect
Read what is inside a keystore or a standalone certificate file.
| When to use | Command |
|---|---|
| List all aliases (summary) | keytool -list -keystore store.p12 -storepass PASS |
| List one alias with full cert details (expiry, SAN, fingerprints) | keytool -list -v -alias NAME -keystore store.p12 -storepass PASS |
| List the JDK default truststore | keytool -list -cacerts -storepass changeit |
| Export a certificate as binary DER | keytool -exportcert -alias NAME -file cert.der -keystore store.p12 -storepass PASS |
Export a certificate as PEM (-rfc) |
keytool -exportcert -alias NAME -rfc -file cert.pem -keystore store.p12 -storepass PASS |
| Print any PEM or DER certificate file | keytool -printcert -file cert.pem |
| Print a CRL file | keytool -printcrl -file ca.crl |
Keystore management
Rename entries, rotate passwords, or remove bad aliases.
| When to use | Command |
|---|---|
| Rename an alias | keytool -changealias -alias OLD -destalias NEW -keystore store.p12 -storepass PASS -noprompt |
| Change the keystore file password | keytool -storepasswd -keystore store.p12 -storepass OLD -new NEW |
| Change an entry key password (JKS only — not PKCS12) | keytool -keypasswd -alias NAME -keystore store.jks -storepass STOREPASS -keypass OLD -new NEW |
| Delete an alias | keytool -delete -alias NAME -keystore store.p12 -storepass PASS -noprompt |
Version and help
| When to use | Command |
|---|---|
| Show all commands | keytool -help |
| Help for one command | keytool -importcert --help |
| Print keytool and JDK tool version | keytool -version |
keytool — command syntax
keytool is mode-based: the first argument after keytool selects the operation (-genkeypair, -list, …). Synopsis from keytool -help on Ubuntu 25.04 (OpenJDK 21.0.9):
keytool -certreq Generates a certificate request
keytool -changealias Changes an entry's alias
keytool -delete Deletes an entry
keytool -exportcert Exports certificate
keytool -genkeypair Generates a key pair
keytool -genseckey Generates a secret key
keytool -gencert Generates certificate from a certificate request
keytool -importcert Imports a certificate or a certificate chain
keytool -importpass Imports a password
keytool -importkeystore Imports one or all entries from another keystore
keytool -keypasswd Changes the key password of an entry
keytool -list Lists entries in a keystore
keytool -printcert Prints the content of a certificate
keytool -printcertreq Prints the content of a certificate request
keytool -printcrl Prints the content of a CRL file
keytool -storepasswd Changes the store password of a keystore
keytool -showinfo Displays security-related information
keytool -version Prints the program versionEach mode accepts its own flags — run keytool -COMMAND --help for the full option list. PKCS12 (.p12) is the default keystore type on OpenJDK 9+; Tomcat and Spring Boot commonly use it. Install the CLI with Install keytool on Ubuntu if keytool: command not found.
keytool — command examples
The examples below use one lab keystore (lab.p12, password changeit) under /tmp/keytool-lab. Every command was run on Ubuntu 25.04 with OpenJDK 21.0.9.
Essential Generate a PKCS12 keystore and list entries
Start a new server identity: create an RSA key pair, self-signed certificate, and PKCS12 file in one step — then confirm the alias is a PrivateKeyEntry.
Prepare a clean lab directory:
mkdir -p /tmp/keytool-lab && cd /tmp/keytool-labGenerate the keystore:
keytool -genkeypair -alias server -keyalg RSA -keysize 2048 -validity 365 \
-storetype PKCS12 -keystore lab.p12 -storepass changeit \
-dname "CN=localhost, OU=Lab, O=GoLinuxCloud, L=City, ST=State, C=US" -nopromptSample output:
Generating 2,048 bit RSA key pair and self-signed certificate (SHA384withRSA) with a validity of 365 days
for: CN=localhost, OU=Lab, O=GoLinuxCloud, L=City, ST=State, C=USList what was created:
keytool -list -keystore lab.p12 -storepass changeitSample output:
Keystore type: PKCS12
Keystore provider: SUN
Your keystore contains 1 entry
server, Jul 2, 2026, PrivateKeyEntry,
Certificate fingerprint (SHA-256): B3:4A:F0:87:14:B7:E6:8F:90:07:91:30:B1:62:58:32:5C:7B:E7:7B:95:15:95:40:C3:C3:DF:14:EB:EA:C4:58PrivateKeyEntry means the alias holds both the private key and certificate — what Tomcat and Spring Boot need for HTTPS.
Essential Create a CSR, sign with OpenSSL, import the CA chain
Replace the self-signed cert with a CA-signed chain: export a CSR from keytool, sign it with a local CA (OpenSSL here), import the CA cert, then import the signed reply on the same alias.
Create the CSR with SAN entries:
keytool -certreq -alias server -file server.csr -keystore lab.p12 -storepass changeit \
-ext "SAN=dns:localhost,ip:127.0.0.1"Inspect the CSR:
keytool -printcertreq -file server.csr | head -15Sample output:
PKCS #10 Certificate Request (Version 1.0)
Subject: CN=localhost, OU=Lab, O=GoLinuxCloud, L=City, ST=State, C=US
...
SubjectAlternativeName [
DNSName: localhost
IPAddress: 127.0.0.1
]Sign with a throwaway CA (OpenSSL — same pattern as a real internal CA):
openssl req -x509 -newkey rsa:2048 -nodes -keyout ca.key -out ca.crt -days 365 \
-subj "/CN=Lab CA" -addext "basicConstraints=critical,CA:TRUE"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server-signed.crt -days 365 -copy_extensions copyallImport the CA, then install the signed reply on alias server:
keytool -importcert -alias labca -file ca.crt -keystore lab.p12 -storepass changeit -noprompt
keytool -importcert -alias server -file server-signed.crt -keystore lab.p12 -storepass changeit -nopromptSample output:
Certificate was added to keystore
Certificate reply was installed in keystoreVerify the chain length:
keytool -list -v -keystore lab.p12 -storepass changeit -alias server | head -12Sample output:
Alias name: server
Creation date: Jul 2, 2026
Entry type: PrivateKeyEntry
Certificate chain length: 2
Certificate[1]:
Owner: CN=localhost, OU=Lab, O=GoLinuxCloud, L=City, ST=State, C=US
Issuer: CN=Lab CAChain length 2 means leaf plus issuing CA — browsers and Java TLS need the intermediate/issuer present, not only the leaf file.
Essential Inspect expiry, issuer, and SHA-256 fingerprint
Before you trust or deploy a cert, list one alias verbosely — this is the usual “what expires when?” check on an unknown keystore.
keytool -list -v -alias server -keystore lab.p12 -storepass changeitSample output (trimmed):
Alias name: server
Entry type: PrivateKeyEntry
Certificate chain length: 2
Certificate[1]:
Owner: CN=localhost, OU=Lab, O=GoLinuxCloud, L=City, ST=State, C=US
Issuer: CN=Lab CA
Valid from: Thu Jul 02 15:10:54 IST 2026 until: Fri Jul 02 15:10:54 IST 2027
Certificate fingerprints:
SHA256: 31:F6:FA:94:FE:39:0C:99:B5:11:4B:8B:BE:E3:64:B5:C2:F8:64:5F:7C:05:74:D3:27:2C:66:95:35:6E:B5:7DCompare that SHA-256 line with keytool -printcert -file or openssl x509 -noout -fingerprint -sha256 before you import a file someone emailed you.
Common Export a certificate to PEM and print it
Share the public certificate without exporting the private key — PEM (-rfc) is what nginx and many tools expect.
Export DER and PEM:
keytool -exportcert -alias server -file server.der -keystore lab.p12 -storepass changeit
keytool -exportcert -alias server -rfc -file server.pem -keystore lab.p12 -storepass changeitSample output:
Certificate stored in file <server.der>
Certificate stored in file <server.pem>Print the PEM file:
keytool -printcert -file server.pem | head -10Sample output:
Owner: CN=localhost, OU=Lab, O=GoLinuxCloud, L=City, ST=State, C=US
Issuer: CN=Lab CA
Serial number: 72b4a19cb1069e9c400708fa5890a5442e1e40b6
Valid from: Thu Jul 02 15:10:54 IST 2026 until: Fri Jul 02 15:10:54 IST 2027
Certificate fingerprints:
SHA256: 31:F6:FA:94:FE:39:0C:99:B5:11:4B:8B:BE:E3:64:B5:C2:F8:64:5F:7C:05:74:D3:27:2C:66:95:35:6E:B5:7D-exportcert on a PrivateKeyEntry exports only the public certificate — never the private key.
Common Rename an alias without regenerating keys
Tomcat server.xml and Spring Boot server.ssl.key-alias must match the keystore alias — rename instead of reissuing when only the name was wrong.
Before:
keytool -list -keystore lab.p12 -storepass changeitRename server to app-server:
keytool -changealias -alias server -destalias app-server -keystore lab.p12 -storepass changeit -nopromptAfter:
keytool -list -keystore lab.p12 -storepass changeitSample output:
Your keystore contains 2 entries
app-server, Jul 2, 2026, PrivateKeyEntry,
Certificate fingerprint (SHA-256): 31:F6:FA:94:FE:39:0C:99:B5:11:4B:8B:BE:E3:64:B5:C2:F8:64:5F:7C:05:74:D3:27:2C:66:95:35:6E:B5:7D
labca, Jul 2, 2026, trustedCertEntry,
Certificate fingerprint (SHA-256): 58:48:86:5E:C3:85:A3:BF:FF:41:0D:C3:2B:DE:89:BB:BE:D4:F5:0D:22:7B:EB:61:A7:E0:C9:14:17:91:80:9BThe private key and chain stay attached — only the alias string changes.
Common Rotate the keystore password
Update the password on a PKCS12 file before you hand it to another team or paste it into a secrets manager.
keytool -storepasswd -keystore lab.p12 -storepass changeit -new newstore
keytool -list -keystore lab.p12 -storepass newstore | head -5
keytool -storepasswd -keystore lab.p12 -storepass newstore -new changeitSample output:
Keystore type: PKCS12
Keystore provider: SUN
Your keystore contains 2 entriesUse -new PASSWORD immediately after -storepass — there is no -newstorepass flag. On PKCS12, the store password protects the whole file; -keypasswd is not supported (see Troubleshooting).
Common Import one alias from another keystore, then delete it
Merge a .p12 from another system, then remove a stale alias — typical when consolidating keystores after a migration.
Create a second keystore and import one alias into lab.p12:
keytool -genkeypair -alias other -keyalg RSA -keysize 2048 -validity 30 \
-storetype PKCS12 -keystore other.p12 -storepass changeit -dname "CN=other" -noprompt
keytool -importkeystore -srckeystore other.p12 -srcstoretype PKCS12 -srcstorepass changeit \
-destkeystore lab.p12 -deststoretype PKCS12 -deststorepass changeit \
-srcalias other -destalias imported-other -nopromptSample output:
Importing keystore other.p12 to lab.p12...List three entries, then delete the import:
keytool -list -keystore lab.p12 -storepass changeit
keytool -delete -alias imported-other -keystore lab.p12 -storepass changeit -noprompt
keytool -list -keystore lab.p12 -storepass changeitSample output after delete:
Your keystore contains 2 entries
app-server, Jul 2, 2026, PrivateKeyEntry,
labca, Jul 2, 2026, trustedCertEntry,Omit -srcalias / -destalias to copy every entry from the source keystore.
Advanced List the JDK default truststore (cacerts)
Java HTTPS clients trust CAs bundled in cacerts unless you point at a custom truststore. List it read-only before you add a private CA.
keytool -list -cacerts -storepass changeit | head -8Sample output:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 113 entries
debian:ac_raiz_fnmt-rcm.pem, Jul 2, 2026, trustedCertEntry,Default password is changeit. Import a private CA with sudo keytool -importcert -alias myca -file ca.crt -cacerts -storepass changeit -noprompt only when you intend to trust that CA JVM-wide — prefer a custom truststore for application-specific CAs.
keytool — when to use / when not
| Use keytool when | Use something else when |
|---|---|
|
|
keytool vs OpenSSL
| Task | keytool | OpenSSL |
|---|---|---|
| Generate RSA/EC key + self-signed cert in a Java keystore | Yes (-genkeypair) |
Yes (req -x509) — PEM files |
| Create CSR | Yes (-certreq) |
Yes (req -new) |
| Sign CSR with a CA | Yes (-gencert if CA key is in keystore) |
Yes (x509 -req) — typical for local CAs |
| Inspect remote HTTPS certificate | No | Yes (s_client) |
| Merge key + cert into PKCS12 for Java | Yes (-genkeypair or -importkeystore) |
Yes (pkcs12 -export) — common interop path |
Manage Java cacerts truststore |
Yes (-importcert -cacerts) |
No |
Use both: OpenSSL for PKI creation and PEM operations; keytool for Java-native stores and cacerts. See OpenSSL cheat sheet for the other half of the workflow.
Related commands
Java TLS and keystore work often sits beside OpenSSL PKI tools and the JDK install itself.
| Command | One line |
|---|---|
| keytool | Java keystore and truststore management |
| openssl | PEM keys, CSRs, chains, PKCS12, live TLS checks |
| java | JVM runtime — install via default-jdk to get keytool |
| keytool install guide | Fix command not found, JAVA_HOME, and apt packages |
More command decks: Linux commands cheat sheet.
keytool — interview corner
What is the difference between a keystore and a truststore in Java?
A keystore usually holds your identity: private key plus certificate chain (Tomcat HTTPS, mutual TLS client cert). A truststore holds trusted public CAs — certificates you accept when validating peers.
keytool uses the same file format for both; the difference is entry type and how the app configures it:
| Store role | Typical entries | Java config |
|---|---|---|
| Keystore | PrivateKeyEntry |
javax.net.ssl.keyStore |
| Truststore | trustedCertEntry |
javax.net.ssl.trustStore |
List entry types:
keytool -list -v -keystore server.p12 -storepass changeitSample line:
app-server, Jul 2, 2026, PrivateKeyEntry,Versus a CA-only import:
labca, Jul 2, 2026, trustedCertEntry,A strong answer is:
A keystore is for my keys and certs; a truststore is for CAs I trust. Same tool and file types, but PrivateKeyEntry means identity, trustedCertEntry means anchor only — apps point keyStore and trustStore at different files or aliases.
Why is PKCS12 preferred over JKS today?
JKS was Java’s legacy proprietary format. PKCS12 (.p12) is an open standard interoperable with OpenSSL, Windows, and modern Java.
Since Java 9 (JEP 229), PKCS12 is the default storetype when you omit -storetype:
keytool -genkeypair -alias demo -keyalg RSA -keysize 2048 -validity 30 \
-keystore demo.p12 -storepass changeit -dname "CN=demo" -noprompt
keytool -list -keystore demo.p12 -storepass changeit | head -3Sample output:
Keystore type: PKCS12Legacy apps that require JKS: -storetype JKS on generate/import, or -importkeystore to convert.
A strong answer is:
PKCS12 is standard, interoperable, and the OpenJDK default since Java 9. I use JKS only when a legacy app demands it; otherwise PKCS12 for Tomcat, Spring Boot, and OpenSSL hand-off.
What happens when you import a CA-signed certificate with -importcert?
If the alias already has a PrivateKeyEntry from -genkeypair and the signed cert matches the CSR, keytool replaces the self-signed cert with the CA reply and builds the chain:
Certificate reply was installed in keystoreIf the public key does not match, you get:
keytool error: java.lang.Exception: Public keys in reply and keystore don't matchThat usually means wrong alias, wrong CSR, or importing someone else’s certificate.
A strong answer is:
importcert on a CSR alias installs the signed reply over the existing private key. The reply must match the key that generated the CSR — alias mix-ups cause the public keys don't match error.
What is the difference between PrivateKeyEntry and trustedCertEntry?
| Entry type | Contains | Typical use |
|---|---|---|
PrivateKeyEntry |
Private key + cert chain | Server HTTPS, client mTLS identity |
trustedCertEntry |
Public certificate only | Imported CA or peer cert you trust |
Importing only a .crt file without a private key creates trustedCertEntry — a common mistake when you meant to load a TLS identity.
A strong answer is:
PrivateKeyEntry means key plus certs — that's your TLS identity. trustedCertEntry is trust-only, no private key — CA imports and peer anchors.
What is the default cacerts password and where is the file?
The default password is changeit. Path depends on JAVA_HOME:
KEYTOOL=$(readlink -f "$(command -v keytool)")
JAVA_HOME=$(dirname "$(dirname "$KEYTOOL")")
ls -l "$JAVA_HOME/lib/security/cacerts"List without modifying:
keytool -list -cacerts -storepass changeit | head -5A strong answer is:
cacerts lives under JAVA_HOME/lib/security, default password changeit. I list with -cacerts before importing private CAs, and prefer a custom truststore over editing global cacerts in production.
What causes Failed to establish chain from reply in keytool?
The signed reply cannot link to a trusted issuer already in the keystore (or cacerts with -trustcacerts). Typical causes:
- Intermediate CA cert not imported before the leaf reply
- Wrong order: leaf imported as new alias instead of reply on CSR alias
- Missing root CA in the store
Fix: import root and intermediate CAs as trustedCertEntry aliases first, then import the server reply on the key alias with -trustcacerts if needed.
A strong answer is:
Chain failure means keytool cannot path-build from the reply to a trust anchor in the keystore. I import intermediate and root CAs first, then install the reply on the original CSR alias.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
keytool: command not found |
JDK not installed or not on PATH |
Install keytool on Ubuntu |
Failed to establish chain from reply |
Missing intermediate/root CA in keystore | Import CA certs first; retry with -trustcacerts |
Public keys in reply and keystore don't match |
Signed cert does not match CSR alias / key | Import reply on the same alias that generated the CSR |
keypasswd … not supported if -storetype is PKCS12 |
PKCS12 uses one password for store and key | Change only -storepasswd; use JKS if you truly need separate key passwords |
Illegal option: -newstorepass |
Wrong flag name | Use -new PASSWORD with -storepasswd and -keypasswd |
trustedCertEntry but you expected HTTPS identity |
Imported .crt only — no private key |
Import PKCS12 from OpenSSL or regenerate with -genkeypair |
| Hostname verification fails in Java client | Cert lacks SAN | Regenerate CSR with -ext "SAN=dns:host,..." |
Wrong cacerts edited |
Multiple JDKs installed | readlink -f $(which keytool) and use that JAVA_HOME |
References
- keytool(1) — Ubuntu man page (noble mirror; Plucky uses the same OpenJDK 21
keytool) - keytool — Java 21 documentation
- On-site: Install keytool on Ubuntu, OpenSSL cheat sheet, PKI concepts, Linux commands cheat sheet

