Import PEM Certificate and Private Key into Java Keystore

keytool cannot import a PEM private key on its own. Learn why -importcert creates trustedCertEntry instead of PrivateKeyEntry, then wrap cert and key with openssl pkcs12 -export and use keytool -importkeystore for a working Java identity entry.

Published

Updated

Read time 7 min read

Reviewed byDeepak Prasad

Import PEM certificate and private key into Java keystore banner with key and vault

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. Commands were run on Ubuntu with OpenJDK 25.

Tested on: Ubuntu 26.04 LTS; OpenJDK 25.0.3; kernel 7.0.0-27-generic.


Prerequisites

Install both tools and gather the PEM pair before you try any import — the fix depends on OpenSSL to bridge PEM into PKCS12.

  • keytool and openssl on PATH. See Install keytool on Ubuntu if the command is missing.
  • PEM files: an X.509 certificate (.crt, .cer, .pem) and matching private key (.key, often PKCS#8 BEGIN 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:

bash
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:

bash
keytool -importcert -alias pem-wrong \
  -file server.crt \
  -keystore wrong.jks -storetype JKS \
  -storepass changeit -noprompt
text
Certificate was added to keystore

That message is misleading on its own. List the keystore to see the actual entry type:

bash
keytool -list -v -keystore wrong.jks -storetype JKS -storepass changeit
text
Alias name: pem-wrong
Entry type: trustedCertEntry

trustedCertEntry 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.

WARNING
If you only imported the .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:

bash
keytool -importcert -alias bad-key \
  -file server.key \
  -keystore bad-key.jks \
  -storepass changeit -noprompt
text
keytool error: java.lang.Exception: Input not an X.509 certificate

A 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:

bash
openssl x509 -in server.crt -noout -pubkey | openssl sha256
openssl pkey -in server.key -pubout | openssl sha256
text
SHA2-256(stdin)= c14fb42f849f18f4c0e2839e671f117c4ca66b0f99dad99e33a81e264297dc2b
SHA2-256(stdin)= c14fb42f849f18f4c0e2839e671f117c4ca66b0f99dad99e33a81e264297dc2b

The 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:

bash
openssl pkcs12 -export \
  -inkey server.key \
  -in server.crt \
  -out server.p12 \
  -name pem-right \
  -passout pass:changeit

Use 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:

bash
keytool -list -v \
  -keystore server.p12 \
  -storetype PKCS12 \
  -storepass changeit \
  -alias pem-right | grep -E "Entry type|Certificate chain length|Owner:|Issuer:"
text
Entry type: PrivateKeyEntry
Certificate chain length: 1
Owner: CN=lab.example.com
Issuer: CN=lab.example.com

For 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:

bash
keytool -importkeystore \
  -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass changeit \
  -destkeystore identity.p12 -deststoretype PKCS12 -deststorepass changeit \
  -noprompt
text
Importing keystore server.p12 to identity.p12...
Entry for alias pem-right successfully imported.
Import command completed:  1 entries successfully imported, 0 entries failed or cancelled

If an older application explicitly requires JKS, import into JKS instead:

bash
keytool -importkeystore \
  -srckeystore server.p12 -srcstoretype PKCS12 -srcstorepass changeit \
  -destkeystore correct.jks -deststoretype JKS -deststorepass changeit \
  -noprompt
text
Importing 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:

bash
keytool -list -v -keystore identity.p12 -storetype PKCS12 -storepass changeit
text
Keystore type: PKCS12
Alias name: pem-right
Entry type: PrivateKeyEntry

PrivateKeyEntry 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:

bash
keytool -list -v -keystore correct.jks -storetype JKS -storepass changeit
text
Keystore type: JKS
Alias name: pem-right
Entry type: PrivateKeyEntry

See 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


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.


Frequently Asked Questions

1. Can keytool import a PEM private key directly?

No. keytool -importcert accepts X.509 certificates only. A PEM private key file produces Input not an X.509 certificate. Wrap the cert and key into PKCS12 with openssl pkcs12 -export, then run keytool -importkeystore to get a PrivateKeyEntry.

2. Why does my PEM import show trustedCertEntry instead of PrivateKeyEntry?

keytool -importcert stores public certificates without private keys as trustedCertEntry. Importing only server.crt from a PEM pair imports the cert but not the key, so Tomcat or Spring Boot cannot use the alias for HTTPS. You need a PKCS12 bundle that includes both parts.

3. What is the correct way to import PEM into a Java keystore?

Run openssl pkcs12 -export -inkey private.key -in certificate.crt -out bundle.p12, then keytool -importkeystore -srckeystore bundle.p12 -srcstoretype PKCS12 -destkeystore identity.p12 -deststoretype PKCS12. List with keytool -list -v and confirm Entry type: PrivateKeyEntry.

4. Should I use JKS or PKCS12 for the destination keystore?

Use PKCS12 (.p12) on OpenJDK 9 and later — it is the default keystore type since JEP 229. JKS still works but prints a proprietary-format warning. Spring Boot and Tomcat accept PKCS12 natively.

5. How do I import a PEM file that contains both cert and key in one file?

If the file is cert followed by key in PEM format, point openssl pkcs12 -export at the cert with -in and the key with -inkey (same path if combined). Then import the resulting .p12 with keytool -importkeystore. keytool still cannot read the combined PEM directly.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …