Convert PEM to a Java keystore
There is no direct PEM-to-JKS conversion, because `keytool` cannot import a private key from a PEM file. The route is two steps: bundle the PEM certificate and key into a PKCS#12 archive with `openssl pkcs12 -export -in certificate.crt -inkey private.key -certfile chain.crt -name myalias -out keystore.p12`, then import that with `keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -destkeystore keystore.jks -deststoretype JKS`. On Java 9 and later you should usually stop after the first step and use the PKCS#12 file directly, since it is the default keystore type and JKS is deprecated.
Step 1 — PEM to PKCS#12 with OpenSSL #
openssl pkcs12 -export \
-in certificate.crt \
-inkey private.key \
-certfile chain.crt \
-name myalias \
-out keystore.p12 Replace these values
| Placeholder | What to put there |
|---|---|
-name myalias | The alias the entry gets inside the keystore. Set it now; renaming later is awkward. |
-certfile chain.crt | Intermediate certificates. Omit if you have none, but a chain is usually required. |
keystore.p12 | The PKCS#12 archive. On Java 9+ this may be your final artefact. |
Step 2 — PKCS#12 to JKS with keytool #
keytool -importkeystore \
-srckeystore keystore.p12 -srcstoretype PKCS12 \
-destkeystore keystore.jks -deststoretype JKS \
-srcalias myalias -destalias myalias keytool prompts for the destination keystore password, then the source (PKCS#12) password.
Verify the result #
keytool -list -v -keystore keystore.jks Expected output
Alias name: myalias Entry type: PrivateKeyEntry Certificate chain length: 2 Certificate[1]: Owner: CN=example.com Issuer: CN=Example Intermediate CA, O=Example CA, C=US Valid from: ... until: ...
Three things to check in that output:
Entry type: PrivateKeyEntry— if it saystrustedCertEntry, the private key did not come across and the keystore cannot terminate TLS.Certificate chain length— should be at least 2 for a publicly trusted certificate. A length of 1 means the intermediates are missing and clients will report unable to get local issuer certificate.- The alias — must match what your application configuration expects.
Importing a trusted CA instead #
If you only need Java to trust a CA, and there is no private key involved, skip PKCS#12 entirely:
keytool -importcert -trustcacerts \
-alias corp-root \
-file root-ca.crt \
-keystore truststore.jks Going the other way #
See convert JKS to PEM.
Frequently asked questions
- Why can't keytool import a PEM private key directly?
keytool -importcertimports certificates only. It has never had a way to read a private key from a PEM file, which is why the PKCS#12 detour exists. This has not changed in any Java release.- Should I still be using JKS?
- Probably not. Java 9 made PKCS#12 the default keystore type, and keytool prints a migration warning every time it touches a JKS file. Unless something specifically demands JKS, stop after the PKCS#12 step and point your application at the .p12.
- What does the alias do?
- It names the entry inside the keystore. Java applications frequently need it in configuration to select which key to use, so set it deliberately with
-nameat export time rather than accepting the default of1. - Do the two passwords have to match?
- The keystore password and the key password are separate in JKS. Many Java servers, Tomcat among them, assume they are the same and fail confusingly when they are not. Setting both to the same value avoids a class of problems that is tedious to diagnose.
References
- keytool reference — the Java keystore tool and its import options
- RFC 7292: PKCS #12 — the archive format, including the MAC OpenSSL 3 rejects on legacy files