| Tested on | Ubuntu 26.04 LTS |
|---|---|
| Package | java-21-openjdk |
| Applies to | Ubuntu, Debian, RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora |
| Privilege | sudo or root |
| Scope | Learn why creates trustedCertEntry instead of PrivateKeyEntry, then wrap cert and key. |
| Related guides | keytool Tutorial Install keytool on Ubuntu List and inspect keystore entries Export certificate in PEM and DER Import PKCS12/PFX into Java keystore |
You received a TLS certificate and private key as separate PEM files — server.crt and server.key — and need them inside a Java keystore for Tomcat, Spring Boot, or a custom SSLContext. keytool is the usual tool, but -importcert alone does not load a private key. Many teams import the certificate, see trustedCertEntry in keytool -list, and wonder why HTTPS still fails.
This guide shows the wrong paths (cert-only import, raw key import), the fix with openssl pkcs12 -export plus keytool -importkeystore, and how to verify a PrivateKeyEntry. The OpenSSL export step matches create PKCS12 from CRT and KEY. Commands were run on Ubuntu with OpenJDK 25.
Prerequisites
Install both tools and gather the PEM pair before you try any import — the fix depends on OpenSSL to bridge PEM into PKCS12.
keytoolandopensslonPATH. See Install keytool on Ubuntu if the command is missing, and OpenSSL forpkcs12 -exportand inspection commands.- PEM files: an X.509 certificate (
.crt,.cer,.pem) and matching private key (.key, often PKCS#8BEGIN PRIVATE KEY). - A destination keystore password you will configure in the application.
For entry-type background (PrivateKeyEntry vs trustedCertEntry), see Java keystore vs truststore.
Understand what keytool can import
keytool routes each input type to a different entry shape. Knowing which command accepts which format saves you from a successful import that still cannot serve HTTPS.
| Input | keytool command | Result in keystore |
|---|---|---|
| X.509 certificate PEM/DER | -importcert |
New alias: trustedCertEntry; existing key alias: certificate reply for PrivateKeyEntry |
| PEM private key only | -importcert |
Error: not an X.509 certificate |
| PKCS12 / PFX (cert + key) | -importkeystore or open as PKCS12 store |
PrivateKeyEntry |
| PEM cert + PEM key (two files) | No single-step keytool import | Use OpenSSL to build PKCS12 first |
In this article, the “wrong approach” imports server.crt into a new alias, so keytool creates trustedCertEntry. That is different from importing a CA-signed reply onto an existing key alias created by -genkeypair — see Create a CSR with keytool and import a CA-signed certificate.
keytool manages keystores; it does not parse standalone PEM private keys. OpenSSL bridges PEM to PKCS12, which keytool understands.
Lab setup: create sample PEM files
The lab uses a self-signed pair under /tmp/keytool-lab. Adjust paths for your real certificate. One OpenSSL command creates both PEM files:
mkdir -p /tmp/keytool-lab && cd /tmp/keytool-lab
openssl req -x509 -newkey rsa:2048 \
-keyout server.key -out server.crt \
-days 365 -nodes \
-subj "/CN=lab.example.com"Both files are PEM-encoded. server.crt is the public certificate; server.key is the private key Tomcat needs for HTTPS. You will import this pair in the steps below.
Wrong approach: import only the certificate PEM
A common mistake is importing server.crt with -importcert and assuming the private key is included. The command succeeds because the certificate is valid X.509 — it just does not attach the key.
Import the certificate alone:
keytool -importcert -alias pem-wrong \
-file server.crt \
-keystore wrong.jks -storetype JKS \
-storepass changeit -nopromptCertificate was added to keystoreThat message is misleading on its own. List the keystore to see the actual entry type:
keytool -list -v -keystore wrong.jks -storetype JKS -storepass changeitAlias name: pem-wrong
Entry type: trustedCertEntrytrustedCertEntry means public certificate only — suitable for a truststore or CA anchor, not for a Java server identity. Spring Boot server.ssl.key-store and Tomcat keystore settings such as certificateKeystoreFile / certificateKeyAlias need an alias that resolves to PrivateKeyEntry.
.crt PEM, you do not have a private key in the keystore. HTTPS connectors will fail or fall back to the wrong entry.
Wrong approach: import the private key PEM with -importcert
-importcert validates X.509 structure only. Feeding it a PEM private key fails immediately:
keytool -importcert -alias bad-key \
-file server.key \
-keystore bad-key.jks \
-storepass changeit -nopromptkeytool error: java.lang.Exception: Input not an X.509 certificateA PEM private key is not a certificate, so there is no keytool flag that imports it directly. Build PKCS12 with OpenSSL first.
Correct approach: OpenSSL PKCS12, then keytool importkeystore
The reliable path wraps cert and key into PKCS12, then copies the entry into your Java keystore with -importkeystore.
Step 1 — Verify the PEM pair and build PKCS12
Confirm the certificate and private key belong together before you bundle them:
openssl x509 -in server.crt -noout -pubkey | openssl sha256
openssl pkey -in server.key -pubout | openssl sha256SHA2-256(stdin)= c14fb42f849f18f4c0e2839e671f117c4ca66b0f99dad99e33a81e264297dc2b
SHA2-256(stdin)= c14fb42f849f18f4c0e2839e671f117c4ca66b0f99dad99e33a81e264297dc2bThe hashes should match. If they do not, the certificate and private key are not a pair.
Combine the PEM pair into a single PKCS12 bundle. The -name flag sets the alias inside the bundle:
openssl pkcs12 -export \
-inkey server.key \
-in server.crt \
-out server.p12 \
-name pem-right \
-passout pass:changeitUse the same alias in Tomcat or Spring Boot if you keep pem-right. If you have a certificate chain, add -certfile ca-bundle.crt so intermediates ship with the identity.
Verify the PKCS12 bundle before importing into another keystore:
keytool -list -v \
-keystore server.p12 \
-storetype PKCS12 \
-storepass changeit \
-alias pem-right | grep -E "Entry type|Certificate chain length|Owner:|Issuer:"Entry type: PrivateKeyEntry
Certificate chain length: 1
Owner: CN=lab.example.com
Issuer: CN=lab.example.comFor this self-signed lab, chain length is 1. If you included a CA bundle with -certfile ca-bundle.crt, the chain length should be greater than 1.
Step 2 — Use the PKCS12 directly or import into another PKCS12 keystore
Spring Boot and Tomcat accept PKCS12 natively (OpenJDK 9+ default per JEP 229). You can deploy server.p12 from Step 1 as-is, or copy it into a dedicated identity file:
keytool -importkeystore \
-srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass changeit \
-destkeystore identity.p12 -deststoretype PKCS12 -deststorepass changeit \
-nopromptImporting keystore server.p12 to identity.p12...
Entry for alias pem-right successfully imported.
Import command completed: 1 entries successfully imported, 0 entries failed or cancelledIf an older application explicitly requires JKS, import into JKS instead:
keytool -importkeystore \
-srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass changeit \
-destkeystore correct.jks -deststoretype JKS -deststorepass changeit \
-nopromptImporting keystore server.p12 to correct.jks...
Entry for alias pem-right successfully imported.
Import command completed: 1 entries successfully imported, 0 entries failed or cancelled
Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore correct.jks -destkeystore correct.jks -deststoretype pkcs12".Step 3 — Verify PrivateKeyEntry
List the PKCS12 destination and confirm the alias shows PrivateKeyEntry, not trustedCertEntry:
keytool -list -v -keystore identity.p12 -storetype PKCS12 -storepass changeitKeystore type: PKCS12
Alias name: pem-right
Entry type: PrivateKeyEntryPrivateKeyEntry confirms both the private key and certificate chain are present. Point your app at identity.p12 (or server.p12) with alias pem-right and server.ssl.key-store-type=PKCS12.
For the legacy JKS path, the same alias should also report PrivateKeyEntry:
keytool -list -v -keystore correct.jks -storetype JKS -storepass changeitKeystore type: JKS
Alias name: pem-right
Entry type: PrivateKeyEntrySee Import PKCS12/PFX into Java keystore when the file is already .p12 or .pfx from a vendor.
Troubleshooting
Use this table when import succeeds but HTTPS still fails or OpenSSL reports a key mismatch:
| Symptom | Likely cause | Fix |
|---|---|---|
trustedCertEntry after import |
Only certificate PEM was imported | Rebuild PKCS12 with -inkey and use -importkeystore |
Input not an X.509 certificate |
Private key passed to -importcert |
Use openssl pkcs12 -export instead |
openssl pkcs12 asks for pass phrase |
Encrypted private key | Add -passin pass:YOUR_KEY_PASS |
| Alias mismatch in Tomcat | -name in openssl ≠ configured alias |
Match alias in keytool -list and server config |
unable to load private key |
Wrong key for certificate | Regenerate bundle with matching pair |
References
- keytool — Java SE 25 documentation
- keytool(1) — Ubuntu man page
- JEP 229: Create PKCS12 Keystores by Default
- , ,
Summary
keytool -importcert imports public certificates as trustedCertEntry when you use a new alias — it never attaches a PEM private key. Importing only server.crt looks successful until you list the store and see no PrivateKeyEntry. The reliable path is openssl pkcs12 -export with -inkey and -in, then keytool -importkeystore into PKCS12 (identity.p12 or server.p12 directly). Use JKS only when legacy config requires it. Confirm with keytool -list -v before wiring the file into Tomcat or Spring Boot.

