Why PKCS#12?
JKS is a format only Java understands. PKCS#12 (extension .p12 or .pfx) is a standard that OpenSSL, Windows, web server tooling and browsers read too. Since Java 9 keytool therefore creates PKCS#12 by default. For JKS files you get this warning:
Warning: The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore ..."
The command
keytool -importkeystore \ -srckeystore keystore.jks -srcstoretype JKS \ -destkeystore keystore.p12 -deststoretype PKCS12
keytool asks for the source password and the new password. All entries are copied: keys with their certificate chain and trusted certificates. Then adjust file name and type in the application, for example in Spring Boot:
server.ssl.key-store=classpath:keystore.p12 server.ssl.key-store-type=PKCS12
The password trap
In JKS each key can have its own password that differs from the keystore password. keytool does not support that for PKCS#12: key and store password are the same. keytool then says:
Warning: Different store and key passwords not supported for PKCS12 KeyStores. Ignoring user-specified -destkeypass value.
If the key had a different password, pass it with -srckeypass. In the result only the store password applies. Remove a separate key-password setting in the application or set it to the same value.
Back to JKS
Some old applications or appliances insist on JKS. The way back is the same command with the types swapped:
keytool -importkeystore \ -srckeystore keystore.p12 -srcstoretype PKCS12 \ -destkeystore keystore.jks -deststoretype JKS
PKCS#12 to PEM for nginx or Apache
If the certificate goes onto a web server or load balancer, you usually need PEM. Use OpenSSL or the certificate converter:
openssl pkcs12 -in keystore.p12 -clcerts -nokeys -out server.crt openssl pkcs12 -in keystore.p12 -cacerts -nokeys -out chain.crt openssl pkcs12 -in keystore.p12 -nocerts -nodes -out server.key
Old Java versions and OpenSSL 3
The encryption inside PKCS#12 has changed. Java 12 and later (as well as Java 8u301 and 11.0.12) write PKCS#12 with AES-256 and SHA-256. Older Java versions used RC2 and 3DES. That causes two problems:
- Old Java cannot read new files. Fix: pass
-J-Dkeystore.pkcs12.legacyto keytool when creating the file. keytool then writes the old format. - OpenSSL 3 cannot read old files and reports
unsupportedorRC2-40-CBC. Fix:openssl pkcs12 -legacy …or rewrite the file with a current keytool.
The Java keystore helper reads both variants and lets you choose “modern” (AES-256) or “compatible” (3DES) when saving.
FAQ
Do I lose anything in the conversion?
Keys, chains and trusted certificates are copied. Only different passwords per key are lost, because PKCS#12 in Java uses a single password.
Can I simply rename the .p12 to .pfx?
Yes. Both are the same format; Windows usually expects the .pfx extension.
What about JCEKS?
JCEKS can also store symmetric keys. keytool copies them to PKCS#12 as well if you specify -srcstoretype JCEKS.
Do I have to convert truststores too?
Not necessarily; Java still reads JKS. The JDK’s cacerts has itself been PKCS#12 since Java 9, but it is read regardless of type.