Zum Inhalt springen
ecdsa.com

PKCS#12 (.pfx/.p12) vs. PEM: Schlüssel und Zertifikate

PEM speichert Schlüssel und Zertifikate als getrennte Textblöcke. PKCS#12 packt sie in eine einzige passwortgeschützte Binärdatei, die Windows, macOS, Java und Browser direkt importieren.
Im VergleichPKCS #12 (PFX)PEM

Die Frage PKCS#12 vs. PEM stellt sich immer dann, wenn ein Schlüssel und ein Zertifikat zwischen Unix-Servern und Plattformen mit eigenen Schlüsselspeichern wandern. PEM-Dateien bestehen aus getrennten, lesbaren Blöcken, die Software auf Basis von OpenSSL direkt lädt; eine PKCS#12-Datei (.p12 oder .pfx) ist ein einziger verschlüsselter Container, den Betriebssysteme und Java in einem Schritt importieren. Dieselben Schlüssel und Zertifikate, eine andere Verpackung – und die Algorithmen der Verpackung entscheiden, ob ein Import gelingt.

Auf einen Blick

PEMPKCS#12 (PFX)
SpezifikationRFC 7468 (Textkodierung von DER)RFC 7292 (PKCS #12 v1.1), RFC 9579 (PBMAC1)
FormatText, ein oder mehrere Blöcke BEGIN … ENDBinärer DER-Container aus „Safe Bags“
EnthältWas immer du in die Datei schreibst: Schlüssel, Zertifikate, CRLsPrivate Schlüssel, Zertifikate, CRLs, Secrets, mit Anzeigenamen und Schlüssel-IDs
SchutzOptional pro Schlüssel (verschlüsseltes PKCS#8)Passwortbasierte Verschlüsselung der Bags plus ein Integritäts-MAC
Standardschutz in OpenSSL 3.6PBES2 mit AES-256-CBC für verschlüsselte SchlüsselPBES2, PBKDF2-HMAC-SHA256, AES-256-CBC, 2.048 Iterationen; HMAC-SHA256-MAC
OpenSSL -legacyNicht anwendbarRC2-40 für Zertifikate, 3DES für Schlüssel, HMAC-SHA1-MAC
Übliche Dateiendungen.pem, .crt, .key.p12, .pfx
Verwendet vonOpenSSL, Webservern, Proxys, Go, Python, Node.jsWindows-Zertifikatsspeicher, macOS-Schlüsselbund, Java KeyStore, Browsern, signtool

Was in einer .pfx steckt

Eine PKCS#12-Datei ist eine Struktur PFX: ein Authenticated Safe aus Inhaltsblöcken, die jeweils Bags enthalten. Private Schlüssel liegen in Einträgen vom Typ pkcs8ShroudedKeyBag (verschlüsseltes PKCS#8), Zertifikate in Einträgen vom Typ certBag (oft ebenfalls in einem verschlüsselten Block), und Bags tragen Attribute wie friendlyName und localKeyId, die einen Schlüssel seinem Zertifikat zuordnen. Ein aus dem Passwort abgeleiteter MAC schützt die Integrität der gesamten Datei; RFC 9579 (2024) ergänzt PBMAC1, das den MAC-Schlüssel mit PBKDF2 statt mit der veralteten KDF von PKCS#12 ableitet.

PEM hat keinen Container: Ein Server wird mit einer Schlüsseldatei und einer Datei für das Zertifikat (oder die Kette) konfiguriert oder mit einer einzigen Datei mit mehreren Blöcken. Der Schutz hängt allein an der Schlüsseldatei – auf Servern ist sie meist gar nicht geschützt, weil der Prozess den Schlüssel lesen muss, ohne dass jemand ein Passwort eintippt.

Konvertieren

Das folgende Skript, ausgeführt mit OpenSSL 3.6.5, packt einen Wegwerf-Schlüssel und ein Wegwerf-Zertifikat in eine PKCS#12-Datei und entpackt sie wieder.

OpenSSL 3.6: PEM in PKCS#12 und zurück
#!/bin/sh
dir=$(mktemp -d)
cd "$dir" || exit 1
openssl req -new -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes -keyout key.pem \
  -subj "/CN=example.com" -days 30 -out cert.pem 2>/dev/null
openssl pkcs12 -export -inkey key.pem -in cert.pem -name demo -passout pass:demo -out bundle.p12
openssl pkcs12 -in bundle.p12 -passin pass:demo -info -noout 2>&1 | grep -E "MAC:|Shrouded|PKCS7 Encrypted"
openssl pkcs12 -in bundle.p12 -passin pass:demo -nodes -out extracted.pem 2>/dev/null
grep -E "^-----BEGIN" extracted.pem
cd / && rm -rf "$dir"
Ausgabe
MAC: sha256, Iteration 2048
PKCS7 Encrypted data: PBES2, PBKDF2, AES-256-CBC, Iteration 2048, PRF hmacWithSHA256
Shrouded Keybag: PBES2, PBKDF2, AES-256-CBC, Iteration 2048, PRF hmacWithSHA256
-----BEGIN CERTIFICATE-----
-----BEGIN PRIVATE KEY-----

Zwischenzertifikate nimmst du mit -certfile chain.pem auf; um nur die Zertifikate zu extrahieren, verwende -nokeys, für den Schlüssel allein -nocerts. Das Flag -nodes (in neueren Releases -noenc) schreibt den Schlüssel unverschlüsselt, behandle die Ausgabe also entsprechend.

Kompatibilität: moderne vs. veraltete Algorithmen

OpenSSL 3.0 hat die Voreinstellungen für den Export von RC2-40 und 3DES mit einem HMAC-SHA1-MAC auf AES-256 mit einem HMAC-SHA256-MAC umgestellt. Viele Programme, die solche Dateien lesen, zogen erst später nach:

  • macOS: Das Security-Framework von Apple importiert moderne PKCS#12-Dateien ab macOS 15; macOS 14 und älter scheitern mit „MAC verification failed during PKCS12 import (wrong password?)“, selbst mit dem richtigen Passwort.
  • Java: JDK 9 hat PKCS#12 zum Standardtyp für Keystores gemacht; JDK 16 (und Updates von 8 und 11 aus dem Jahr 2021) hat die eigene Voreinstellung von Java auf PBES2 mit AES-256 und einem HMAC-SHA256-MAC umgestellt, und aktuelle Versionen lesen Dateien von OpenSSL 3.
  • Windows: Aktuelle Releases importieren PFX-Dateien mit AES-256; sehr alte Versionen von Windows Server brauchen möglicherweise die Legacy-Form.
  • OpenSSL 3 beim Lesen alter Dateien: Dateien, deren Zertifikate mit RC2-40 verschlüsselt sind (der Standard von OpenSSL 1.1 und das, was Exporte mit -legacy verwenden, wenn RC2 einkompiliert ist), lassen sich nur mit -legacy laden, das den Legacy-Provider lädt. Ohne ihn gibt OpenSSL 3.6.5 für RC2-40-CBC die Meldung error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported aus, und Node.js 26 lehnt die Datei mit Unsupported PKCS12 PFX data ab. Dateien, die nur 3DES und einen HMAC-SHA1-MAC verwenden, lassen sich ohne den Legacy-Provider laden.

Wenn eine moderne Datei auf einem bekanntermaßen alten Ziel scheitert, exportiere mit openssl pkcs12 -export -legacy … oder wähle die Algorithmen explizit (-keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES -macalg SHA1), und behandle diese Datei bei der Übertragung als schwach geschützt.

Die Fehlermeldungen führen hier in die Irre: „MAC verification failed“ oder „wrong password“ bedeutet meist, dass das lesende Programm den MAC- oder Verschlüsselungsalgorithmus nicht unterstützt, und nicht, dass das Passwort falsch ist. Untersuche die Datei mit openssl pkcs12 -info -noout (bei alten Dateien mit -legacy), um zu sehen, welche Algorithmen verwendet wurden, bevor du Passwörter rätst.

PKCS#12 als Keystore

Java behandelt eine PKCS#12-Datei als Keystore: keytool -list -keystore bundle.p12 -storetype PKCS12 zeigt ihre Einträge, und der friendlyName wird zum Alias. Ein Keystore kann mehrere Schlüsseleinträge und vertrauenswürdige Zertifikate enthalten, was eine PEM-Datei ohne Namenskonventionen nicht ausdrücken kann. Truststores sind ein Sonderfall: Ein PKCS#12-Truststore, der nur Zertifikate enthält, braucht Java-spezifische Attribute, die die Zertifikate als vertrauenswürdig markieren; deshalb ist keytool -importcert der zuverlässige Weg, einen solchen Truststore zu erstellen. Die meisten anderen Plattformen ignorieren diese Java-Attribute und ordnen Schlüssel und Zertifikate beim Import über übereinstimmende Werte von localKeyId einander zu.

Wann welches Format passt

  • TLS auf Linux-Servern, Reverse Proxys, Kubernetes-Ingress: Schlüssel in PEM und Zertifikat mit vollständiger Kette.
  • Zertifikatsimporte in Windows IIS, Azure App Service und Key Vault: PKCS#12.
  • TLS mit Java und Spring Boot: ein PKCS#12-Keystore (oder PEM, das neuere Versionen von Spring Boot direkt akzeptieren).
  • Client-Zertifikate für Browser und Mobilgeräte: PKCS#12 mit einem starken Passwort, getrennt vom Passwort zugestellt.
  • Codesignatur mit signtool oder jarsigner: PKCS#12, sofern der Schlüssel überhaupt in einer Datei liegt; öffentlich vertrauenswürdige Signaturschlüssel für die Codesignatur müssen seit 2023 in Hardware liegen.
  • Untersuchung und Debugging: PEM oder der PFX-Inspektor, der Bags und Algorithmen lokal auflistet, ohne den Schlüssel offenzulegen.

Hinweise zur Migration

  1. Nimm die vollständige Kette auf, wenn du eine PKCS#12-Datei für Server oder Clients erstellst, und zwar mit dem Leaf-Zertifikat zuerst; fehlende Zwischenzertifikate sind der häufigste Fehler nach dem Import.
  2. Gleiche Schlüssel und Zertifikat ab, bevor du sie verpackst: Der Schlüssel- und Zertifikats-Matcher vergleicht ihre öffentlichen Schlüssel.
  3. Wähle die Algorithmen für das älteste lesende System und rüste danach auf: Exportiere mit modernen Voreinstellungen neu, sobald die alten Plattformen verschwunden sind.
  4. Verwende starke, zufällige Passwörter für PKCS#12-Dateien, die verschickt werden, denn die Datei lässt sich offline angreifen; die Zahl von 2.048 PBKDF2-Iterationen, die OpenSSL standardmäßig verwendet, ist gemessen an den Maßstäben der Passwortspeicherung niedrig.
  5. Lass extrahierte Schlüssel nicht herumliegen: Nachdem du eine .pfx für einen Server in PEM konvertiert hast, schränke die Dateiberechtigungen ein und lösche temporäre Kopien.

Quellen

Alle Vergleiche