Warum PKCS#12?
JKS ist ein Format, das nur Java versteht. PKCS#12 (Endung .p12 oder .pfx) ist ein Standard, den auch OpenSSL, Windows, nginx-Werkzeuge und Browser lesen. Seit Java 9 erzeugt keytool deshalb standardmäßig PKCS#12. Bei JKS-Dateien erscheint die Warnung:
Warning: The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore ..."
Der Befehl
keytool -importkeystore \ -srckeystore keystore.jks -srcstoretype JKS \ -destkeystore keystore.p12 -deststoretype PKCS12
keytool fragt nach dem Kennwort der Quelle und dem neuen Kennwort. Alle Einträge werden übernommen: Schlüssel mit Zertifikatskette und vertrauenswürdige Zertifikate. Danach in der Anwendung Dateiname und Typ anpassen, zum Beispiel in Spring Boot:
server.ssl.key-store=classpath:keystore.p12 server.ssl.key-store-type=PKCS12
Die Kennwort-Falle
In JKS kann jeder Schlüssel ein eigenes Kennwort haben, das sich vom Keystore-Kennwort unterscheidet. PKCS#12 kennt das in keytool nicht: Schlüssel- und Store-Kennwort sind gleich. keytool meldet dann:
Warning: Different store and key passwords not supported for PKCS12 KeyStores. Ignoring user-specified -destkeypass value.
Hatte der Schlüssel ein anderes Kennwort, gib es mit -srckeypass an. Im Ergebnis gilt nur noch das Store-Kennwort. Entferne in der Anwendung eine separate key-password-Einstellung oder setz sie auf denselben Wert.
Zurück nach JKS
Manche alten Anwendungen oder Appliances verlangen JKS. Der Weg zurück ist derselbe Befehl mit vertauschten Typen:
keytool -importkeystore \ -srckeystore keystore.p12 -srcstoretype PKCS12 \ -destkeystore keystore.jks -deststoretype JKS
PKCS#12 in PEM für nginx oder Apache
Soll das Zertifikat auf einen Webserver oder Load Balancer, brauchst du meist PEM. Das geht mit OpenSSL oder im Zertifikat-Konverter:
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
Alte Java-Versionen und OpenSSL 3
Die Verschlüsselung innerhalb von PKCS#12 hat sich geändert. Java 12 und neuer (sowie Java 8u301 und 11.0.12) schreiben PKCS#12 mit AES-256 und SHA-256. Ältere Java-Versionen nutzten RC2 und 3DES. Daraus ergeben sich zwei Probleme:
- Altes Java kann neue Dateien nicht lesen. Lösung: beim Erzeugen
-J-Dkeystore.pkcs12.legacyan keytool übergeben. Dann schreibt keytool das alte Format. - OpenSSL 3 kann alte Dateien nicht lesen und meldet
unsupportedoderRC2-40-CBC. Lösung:openssl pkcs12 -legacy …oder die Datei mit aktuellem keytool neu schreiben.
Der Java-Keystore-Helfer liest beide Varianten und lässt dich beim Speichern zwischen „modern“ (AES-256) und „kompatibel“ (3DES) wählen.
FAQ
Verliere ich bei der Umwandlung etwas?
Schlüssel, Ketten und vertrauenswürdige Zertifikate werden übernommen. Nur unterschiedliche Kennwörter je Schlüssel gehen verloren, weil PKCS#12 in Java ein gemeinsames Kennwort nutzt.
Kann ich die .p12 einfach in .pfx umbenennen?
Ja. Beides ist dasselbe Format, Windows erwartet meist die Endung .pfx.
Was ist mit JCEKS?
JCEKS kann zusätzlich symmetrische Schlüssel speichern. keytool überträgt sie ebenfalls nach PKCS#12, wenn du -srcstoretype JCEKS angibst.
Muss ich Truststores auch umwandeln?
Nicht zwingend, Java liest JKS weiterhin. Das cacerts des JDK ist seit Java 9 selbst schon PKCS#12, wird aber unabhängig vom Typ gelesen.