{"id":177,"date":"2026-06-17T16:33:28","date_gmt":"2026-06-17T16:33:28","guid":{"rendered":"https:\/\/shattered.io\/de\/2026\/06\/17\/openssl-tutorial-zertifikate\/"},"modified":"2026-06-17T16:34:46","modified_gmt":"2026-06-17T16:34:46","slug":"openssl-tutorial-zertifikate","status":"publish","type":"post","link":"https:\/\/shattered.io\/de\/2026\/06\/17\/openssl-tutorial-zertifikate\/","title":{"rendered":"OpenSSL-Tutorial: Schl\u00fcssel und Zertifikate in 12 Schritten [2026]"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">OpenSSL ist das meistgenutzte Kryptografie-Toolkit der Welt und bildet das Fundament f\u00fcr HTTPS, VPNs, E-Mail-Verschl\u00fcsselung und digitale Zertifikate. Version <strong>3.5.5 LTS<\/strong> (Long-Term-Support bis April 2030) ist der empfohlene Stand f\u00fcr Produktivumgebungen, w\u00e4hrend <strong>4.0.0<\/strong> (ver\u00f6ffentlicht am 14. April 2026) die neuesten Post-Quantum-Algorithmen ML-KEM und ML-DSA mitbringt. Dieses Tutorial f\u00fchrt dich in 12 konkreten Schritten durch die wichtigsten OpenSSL-Operationen: von der Schl\u00fcsselgenerierung \u00fcber den Aufbau einer eigenen Certificate Authority bis hin zur TLS-1.3-Verbindungspr\u00fcfung.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das Keyword &#8220;openssl&#8221; wird in Deutschland 5.400-mal pro Monat gesucht, bei niedrigem Wettbewerb. Der Grund: Viele Entwickler und Systemadministratoren kennen die grundlegenden Befehle, verstehen aber nicht, was dahintersteckt. Dieses Tutorial schlie\u00dft diese L\u00fccke mit produktionsreifen Beispielen, erkl\u00e4rt die Sicherheitsparameter und zeigt, welche CVEs in 2025\/2026 zum sofortigen Update zwingen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"voraussetzungen\">Voraussetzungen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Bevor du startest, stelle sicher, dass folgende Komponenten vorhanden sind:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Komponente<\/th><th>Mindestversion<\/th><th>Empfohlen<\/th><th>Zweck<\/th><\/tr><\/thead><tbody><tr><td>OpenSSL<\/td><td>3.0.x<\/td><td><strong>3.5.5 LTS<\/strong><\/td><td>Alle Krypto-Operationen<\/td><\/tr><tr><td>Linux (Debian\/Ubuntu)<\/td><td>Ubuntu 22.04<\/td><td>Ubuntu 24.04 LTS<\/td><td>Betriebssystem<\/td><\/tr><tr><td>Bash\/Zsh<\/td><td>Bash 5.0<\/td><td>Bash 5.2+<\/td><td>Befehlsausf\u00fchrung<\/td><\/tr><tr><td>Root- oder sudo-Zugriff<\/td><td>sudo<\/td><td>sudo<\/td><td>Pakete installieren<\/td><\/tr><tr><td>Python 3 (optional)<\/td><td>3.10<\/td><td>3.12<\/td><td>Zertifikat-Analyse-Skripte<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Warum OpenSSL 3.5.5 LTS?<\/strong> Die Version schlie\u00dft kritische Sicherheitsl\u00fccken der Reihe 3.0 bis 3.4, darunter CVE-2025-15467 (High-Severity RCE in CMS AuthEnvelopedData-AEAD-Parsing). OpenSSL 1.1.1 erhielt seit September 2023 keine Sicherheits-Updates mehr und ist in Produktivumgebungen nicht mehr vertretbar. Systeme auf Ubuntu 20.04, die noch die vorinstallierte OpenSSL-1.1.1-Version nutzen, sollten auf Ubuntu 22.04 oder 24.04 migriert werden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-1-openssl-installieren-und-version-pruefen\">Schritt 1: OpenSSL installieren und Version pr\u00fcfen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Unter Ubuntu\/Debian ist OpenSSL 3.x seit Ubuntu 22.04 in den Standardrepositories enthalten. Auf \u00e4lteren Systemen muss aus den Quellen kompiliert oder ein alternatives Repository genutzt werden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Paketquellen aktualisieren und OpenSSL installieren\nsudo apt update && sudo apt install -y openssl\n\n# Installierte Version pr\u00fcfen\nopenssl version -a\n\n# Erwartete Ausgabe (gek\u00fcrzt):\n# OpenSSL 3.5.5 8 Jun 2026 (Library: OpenSSL 3.5.5 8 Jun 2026)\n# built on: reproducible build, date unspecified\n# platform: linux-x86_64\n# OPENSSLDIR: \"\/usr\/lib\/ssl\"\n# ENGINESDIR: \"\/usr\/lib\/x86_64-linux-gnu\/engines-3\"\n\n# Alle verf\u00fcgbaren Digest-Algorithmen auflisten\nopenssl list -digest-algorithms | head -10\n\n# Alle verf\u00fcgbaren Cipher Suites auflisten\nopenssl list -cipher-algorithms | head -10\n\n# TLS-1.3-Unterst\u00fctzung pr\u00fcfen\nopenssl s_client -connect google.com:443 -tls1_3 -brief 2>&1 | grep Protocol<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Unter Windows l\u00e4sst sich OpenSSL 3.5.x \u00fcber den <a href=\"https:\/\/www.openssl.org\/source\/\" rel=\"noopener noreferrer\" target=\"_blank\">offiziellen Quell-Download<\/a> oder \u00fcber Chocolatey (<code>choco install openssl<\/code>) installieren. macOS-Nutzer greifen auf Homebrew zur\u00fcck: <code>brew install openssl@3<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Wichtiger Hinweis f\u00fcr macOS:<\/strong> Das Betriebssystem liefert unter <code>\/usr\/bin\/openssl<\/code> noch LibreSSL aus, nicht OpenSSL. Nach <code>brew install openssl@3<\/code> muss der Pfad angepasst werden: <code>export PATH=\"\/opt\/homebrew\/opt\/openssl@3\/bin:$PATH\"<\/code>. Andernfalls werden Homebrew-OpenSSL-Befehle von LibreSSL abgefangen, was zu unterschiedlichem Verhalten f\u00fchren kann.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-2-rsa-schluesselpaar-generieren\">Schritt 2: RSA-Schl\u00fcsselpaar generieren<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">RSA ist der am weitesten verbreitete Algorithmus f\u00fcr asymmetrische Verschl\u00fcsselung und digitale Signaturen. F\u00fcr neue Zertifikate empfiehlt das BSI (Technische Richtlinie TR-02102-2) mindestens <strong>3.072 Bit<\/strong> f\u00fcr eine Sicherheit bis 2030 und <strong>4.096 Bit<\/strong> dar\u00fcber hinaus. RSA 2.048 Bit galt bis Ende 2025 als akzeptabel, sollte aber f\u00fcr neue Deployments nicht mehr verwendet werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ab OpenSSL 3.x wird f\u00fcr die Schl\u00fcsselgenerierung der Befehl <code>genpkey<\/code> empfohlen, der direkt PKCS#8-Format ausgibt. Der \u00e4ltere Befehl <code>genrsa<\/code> funktioniert weiterhin, gibt aber PKCS#1-Format aus, was bei manchen Anwendungen zu Kompatibilit\u00e4tsproblemen f\u00fchren kann.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Moderner Weg: genpkey mit PKCS#8-Format (empfohlen ab OpenSSL 3.x)\nopenssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out private-rsa.key\n\n# Mit AES-256-CBC-Verschl\u00fcsselung sch\u00fctzen (Passphrase wird interaktiv abgefragt)\nopenssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 \\\n  -aes-256-cbc -out private-rsa-encrypted.key\n\n# \u00d6ffentlichen Schl\u00fcssel extrahieren\nopenssl pkey -in private-rsa.key -pubout -out public-rsa.key\n\n# Schl\u00fcsselinformationen anzeigen\nopenssl pkey -in private-rsa.key -text -noout | head -5\n\n# Erwartete Ausgabe:\n# RSA Private-Key: (4096 bit, 2 primes)\n# publicExponent: 65537 (0x10001)\n\n# Alternativer Weg (PKCS#1-Format, \u00e4ltere Syntax):\nopenssl genrsa -out private-pkcs1.key 4096<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Die Schl\u00fcsselgenerierung mit 4.096 Bit dauert auf moderner Hardware weniger als eine Sekunde. Der \u00f6ffentliche Exponent ist standardm\u00e4\u00dfig 65537 (0x10001), ein primzahlfreundlicher Wert, der schnelle Verschl\u00fcsselung und Signaturverifizierung erm\u00f6glicht. Die Details zu RSA-Verschl\u00fcsselung und wie sie in Node.js-Anwendungen eingebettet wird, erkl\u00e4re ich im Artikel <a href=\"\/de\/rsa-encryption-nodejs\/\">RSA-Verschl\u00fcsselung in Node.js: 11 Schritte [2026]<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-3-ecdsa-schluesselpaar-generieren-bevorzugter-ansatz\">Schritt 3: ECDSA-Schl\u00fcsselpaar generieren (bevorzugter Ansatz)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Elliptic Curve Digital Signature Algorithm (ECDSA) mit der Kurve <strong>P-384<\/strong> oder <strong>P-256<\/strong> bietet bei deutlich kleineren Schl\u00fcsseln dieselbe Sicherheitsst\u00e4rke wie RSA 7.680 Bit (P-384) bzw. RSA 3.072 Bit (P-256). TLS-1.3-Server und moderne Browser bevorzugen ECDSA gegen\u00fcber RSA, weil der Handshake schneller abl\u00e4uft und die \u00fcbertragenen Datenmengen geringer sind.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Algorithmus<\/th><th>Schl\u00fcssell\u00e4nge<\/th><th>Sicherheitsst\u00e4rke<\/th><th>Signatur-Gr\u00f6\u00dfe<\/th><th>BSI-Empfehlung bis<\/th><\/tr><\/thead><tbody><tr><td>RSA<\/td><td>2.048 Bit<\/td><td>112 Bit<\/td><td>256 Byte<\/td><td>2025<\/td><\/tr><tr><td>RSA<\/td><td>3.072 Bit<\/td><td>128 Bit<\/td><td>384 Byte<\/td><td>2030<\/td><\/tr><tr><td>RSA<\/td><td>4.096 Bit<\/td><td>140 Bit<\/td><td>512 Byte<\/td><td>2030+<\/td><\/tr><tr><td>ECDSA P-256<\/td><td>256 Bit<\/td><td>128 Bit<\/td><td>64 Byte<\/td><td>2030<\/td><\/tr><tr><td>ECDSA P-384<\/td><td>384 Bit<\/td><td>192 Bit<\/td><td>96 Byte<\/td><td>2030+<\/td><\/tr><tr><td>Ed25519<\/td><td>256 Bit<\/td><td>128 Bit<\/td><td>64 Byte<\/td><td>2030<\/td><\/tr><tr><td>ML-DSA-65 (Post-Quantum)<\/td><td>1.952 Bit<\/td><td>128 Bit (PQ-sicher)<\/td><td>3.293 Byte<\/td><td>nach 2030<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code># ECDSA P-384 Schl\u00fcssel generieren (BSI-empfohlen bis 2030+)\nopenssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-384 -out private-ec-p384.key\n\n# ECDSA P-256 Schl\u00fcssel generieren (maximale Kompatibilit\u00e4t)\nopenssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out private-ec-p256.key\n\n# Ed25519 Schl\u00fcssel generieren (schnellste Signierung, keine Kurven-Parameter)\nopenssl genpkey -algorithm Ed25519 -out private-ed25519.key\n\n# \u00d6ffentlichen EC-Schl\u00fcssel extrahieren\nopenssl pkey -in private-ec-p384.key -pubout -out public-ec-p384.key\n\n# EC-Schl\u00fcsselinformationen anzeigen\nopenssl pkey -in private-ec-p384.key -text -noout\n\n# Erwartete Ausgabe:\n# EC Key (id: 408)\n# Public-Key: (384 bit)\n# pub:\n#     04:b4:e3:a7:...\n# ASN1 OID: secp384r1\n# NIST CURVE: P-384<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Die Entscheidung zwischen P-256 und P-384 h\u00e4ngt vom Schutzbedarf ab. F\u00fcr interne Dienste, die bis 2030 in Betrieb sind, reicht P-256. F\u00fcr Zertifikate mit l\u00e4ngerer Lebensdauer oder h\u00f6herem Schutzbedarf empfiehlt die <a href=\"https:\/\/www.bsi.bund.de\/SharedDocs\/Downloads\/DE\/BSI\/Publikationen\/TechnischeRichtlinien\/TR02102\/BSI-TR-02102.pdf\" rel=\"noopener noreferrer\" target=\"_blank\">BSI Technische Richtlinie TR-02102<\/a> P-384. Die technischen Details zu elliptischer Kurven-Kryptografie erkl\u00e4rt der <a href=\"https:\/\/nvlpubs.nist.gov\/nistpubs\/FIPS\/NIST.FIPS.186-5.pdf\" rel=\"noopener noreferrer\" target=\"_blank\">NIST FIPS 186-5 Standard<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-4-selbstsigniertes-zertifikat-erstellen\">Schritt 4: Selbstsigniertes Zertifikat erstellen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Selbstsignierte Zertifikate sind f\u00fcr Entwicklungsumgebungen, interne Dienste und Testaufbauten ideal. Browser und Clients vertrauen ihnen standardm\u00e4\u00dfig nicht, was bei \u00f6ffentlichen Diensten ein Problem darstellt. F\u00fcr \u00f6ffentliche Server sollte stattdessen eine externe CA wie Let&#8217;s Encrypt genutzt werden. F\u00fcr rein interne Infrastruktur bietet eine eigene CA (Schritt 6) die bessere Alternative zu einzelnen selbstsignierten Zertifikaten.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Selbstsigniertes Zertifikat mit EC P-384 Schl\u00fcssel in einem Schritt\nopenssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-384 \\\n  -keyout self-signed.key \\\n  -out self-signed.crt \\\n  -days 365 \\\n  -noenc \\\n  -subj \"\/C=DE\/ST=Bayern\/L=Muenchen\/O=MeinUnternehmen GmbH\/CN=dev.example.com\" \\\n  -addext \"subjectAltName=DNS:dev.example.com,DNS:localhost,IP:127.0.0.1\"\n\n# Zertifikat vollst\u00e4ndig anzeigen\nopenssl x509 -in self-signed.crt -text -noout\n\n# Relevante Ausgabe-Ausz\u00fcge:\n# Certificate:\n#   Data:\n#     Version: 3 (0x2)\n#     Serial Number: 7f:3a:b2:...\n#     Signature Algorithm: ecdsa-with-SHA384\n#     Issuer: C=DE, ST=Bayern, L=Muenchen, O=MeinUnternehmen GmbH, CN=dev.example.com\n#     Validity\n#         Not Before: Jun 17 09:00:00 2026 GMT\n#         Not After : Jun 17 09:00:00 2027 GMT\n#     Subject Alternative Name:\n#         DNS:dev.example.com, DNS:localhost, IP Address:127.0.0.1<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Kritischer Fallstrick:<\/strong> Seit 2017 lehnen alle g\u00e4ngigen Browser Zertifikate ohne Subject Alternative Names (SANs) ab, auch wenn der Common Name (CN) korrekt gesetzt ist. Der Parameter <code>-addext \"subjectAltName=...\"<\/code> ist deshalb Pflicht, nicht optional. Ohne SAN erscheint in Chrome und Firefox der Fehler <code>NET::ERR_CERT_COMMON_NAME_INVALID<\/code>. Das Zertifikat sieht in openssl-Ausgaben korrekt aus, wird aber vom Browser trotzdem abgelehnt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-5-certificate-signing-request-csr-erstellen\">Schritt 5: Certificate Signing Request (CSR) erstellen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ein CSR (Certificate Signing Request) enth\u00e4lt den \u00f6ffentlichen Schl\u00fcssel und die Identit\u00e4tsinformationen, die an eine Certificate Authority (CA) gesendet werden. Die CA pr\u00fcft die Angaben und stellt daraufhin ein signiertes Zertifikat aus. F\u00fcr Let&#8217;s Encrypt oder kommerzielle CAs ist dieser Weg der Standard. F\u00fcr die eigene interne CA (n\u00e4chster Schritt) wird der CSR ebenfalls ben\u00f6tigt.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Schritt 5a: Privaten Schl\u00fcssel generieren (falls noch nicht vorhanden)\nopenssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-384 -out server.key\n\n# Schritt 5b: CSR erstellen\nopenssl req -new \\\n  -key server.key \\\n  -out server.csr \\\n  -subj \"\/C=DE\/ST=Bayern\/L=Muenchen\/O=MeinUnternehmen GmbH\/OU=IT\/CN=example.com\" \\\n  -addext \"subjectAltName=DNS:example.com,DNS:www.example.com\"\n\n# CSR-Inhalt pr\u00fcfen\nopenssl req -in server.csr -text -noout | grep -A 5 \"Subject\"\n\n# CSR-Signatur verifizieren (pr\u00fcft die Integrit\u00e4t des CSR)\nopenssl req -in server.csr -verify -noout\n# Erwartete Ausgabe: Certificate request self-signature verify OK\n\n# CSR als Base64 anzeigen (f\u00fcr \u00dcbertragung an externe CA)\ncat server.csr<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Den fertigen CSR schickst du an deine gew\u00fcnschte CA. Kommerzielle CAs wie DigiCert, Sectigo oder GlobalSign verlangen eine Domain-Validierung per E-Mail oder DNS-Record. Let&#8217;s Encrypt automatisiert diesen Prozess vollst\u00e4ndig \u00fcber das ACME-Protokoll. F\u00fcr eine kostenlose Alternative mit automatischer Erneuerung erkl\u00e4re ich den gesamten Prozess im Artikel <a href=\"\/de\/lets-encrypt-zertifikat-einrichten\/\">Let&#8217;s Encrypt: Zertifikat in 12 Schritten einrichten [2026]<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-6-eigene-certificate-authority-ca-aufbauen\">Schritt 6: Eigene Certificate Authority (CA) aufbauen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Eine eigene CA ist f\u00fcr interne Infrastruktur die beste Wahl: keine externen Abh\u00e4ngigkeiten, vollst\u00e4ndige Kontrolle \u00fcber Ausstellung und Widerruf, und Clients k\u00f6nnen das CA-Zertifikat einmalig importieren und vertrauen danach allen davon signierten Zertifikaten automatisch. Typische Einsatzfelder sind interne APIs, Kubernetes-Cluster, VPN-Dienste und Micro-Service-Architekturen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Eine robuste CA-Infrastruktur besteht aus einer Root-CA (offline aufbewahrt) und mindestens einer Intermediate-CA (f\u00fcr die t\u00e4gliche Zertifikatsausstellung). F\u00fcr einfache Setups reicht eine einzelne CA ohne Intermediate-Ebene.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n# CA-Verzeichnisstruktur anlegen\nmkdir -p myCA\/{certs,crl,newcerts,private,csr}\nchmod 700 myCA\/private\ntouch myCA\/index.txt\necho 1000 > myCA\/serial\necho 1000 > myCA\/crlnumber\n\n# CA-Schl\u00fcssel generieren (stark verschl\u00fcsseln, offline aufbewahren!)\nopenssl genpkey -algorithm EC \\\n  -pkeyopt ec_paramgen_curve:P-384 \\\n  -aes-256-cbc \\\n  -pass pass:SICHERES_CA_PASSWORT \\\n  -out myCA\/private\/ca.key\nchmod 400 myCA\/private\/ca.key\n\n# CA-Zertifikat erstellen (20 Jahre Laufzeit f\u00fcr Root-CA)\nopenssl req -new -x509 \\\n  -key myCA\/private\/ca.key \\\n  -passin pass:SICHERES_CA_PASSWORT \\\n  -out myCA\/certs\/ca.crt \\\n  -days 7300 \\\n  -subj \"\/C=DE\/ST=Bayern\/O=MeinUnternehmen GmbH\/CN=MeinUnternehmen Root CA\" \\\n  -addext \"basicConstraints=critical,CA:TRUE,pathlen:1\" \\\n  -addext \"keyUsage=critical,keyCertSign,cRLSign\" \\\n  -addext \"subjectKeyIdentifier=hash\"\n\n# CA-Zertifikat pr\u00fcfen\nopenssl x509 -in myCA\/certs\/ca.crt -text -noout | grep -E \"(Issuer|Subject|Not|CA:)\"\n\n# Erwartete Ausgabe (Auszug):\n# Issuer: C=DE, ST=Bayern, O=MeinUnternehmen GmbH, CN=MeinUnternehmen Root CA\n# Not Before: Jun 17 09:00:00 2026 GMT\n# Not After : Jun 14 09:00:00 2046 GMT\n# CA:TRUE<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Die Extension <code>basicConstraints=critical,CA:TRUE<\/code> kennzeichnet das Zertifikat als CA-Zertifikat. <code>pathlen:1<\/code> erlaubt genau eine weitere CA-Ebene (Intermediate CA) darunter. Der Parameter <code>keyUsage=critical,keyCertSign,cRLSign<\/code> schr\u00e4nkt die Verwendung ausschlie\u00dflich auf das Signieren von Zertifikaten und Widerrufslisten ein. Das <code>critical<\/code>-Flag erzwingt, dass Clients diese Extension verstehen und ber\u00fccksichtigen m\u00fcssen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-7-serverzertifikat-mit-eigener-ca-signieren\">Schritt 7: Serverzertifikat mit eigener CA signieren<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Mit der im vorherigen Schritt erstellten CA k\u00f6nnen nun Serverzertifikate f\u00fcr interne Dienste ausgestellt werden. Clients, die dem CA-Zertifikat vertrauen, akzeptieren alle davon signierten Zertifikate automatisch, ohne weitere Konfiguration.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># 1. Server-Schl\u00fcssel generieren\nopenssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-384 -out server.key\n\n# 2. CSR erstellen\nopenssl req -new \\\n  -key server.key \\\n  -out server.csr \\\n  -subj \"\/C=DE\/ST=Bayern\/O=MeinUnternehmen GmbH\/CN=api.intern.example.com\"\n\n# 3. Konfigurationsdatei f\u00fcr Extensions (WICHTIG f\u00fcr SAN und korrekte KeyUsage)\ncat > server-ext.cnf << 'EOF'\n[ v3_req ]\nsubjectAltName = @alt_names\nkeyUsage = critical, digitalSignature, keyEncipherment\nextendedKeyUsage = serverAuth\nbasicConstraints = CA:FALSE\n\n[ alt_names ]\nDNS.1 = api.intern.example.com\nDNS.2 = *.intern.example.com\nIP.1 = 192.168.1.100\nEOF\n\n# 4. Zertifikat mit CA signieren (365 Tage Laufzeit)\nopenssl x509 -req \\\n  -in server.csr \\\n  -CA myCA\/certs\/ca.crt \\\n  -CAkey myCA\/private\/ca.key \\\n  -passin pass:SICHERES_CA_PASSWORT \\\n  -CAcreateserial \\\n  -out server.crt \\\n  -days 365 \\\n  -extfile server-ext.cnf \\\n  -extensions v3_req\n\n# 5. Zertifikatskette vollst\u00e4ndig verifizieren\nopenssl verify -CAfile myCA\/certs\/ca.crt server.crt\n# Erwartete Ausgabe: server.crt: OK<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Empfehlung zur Laufzeit:<\/strong> Verwende f\u00fcr Serverzertifikate maximal 365 Tage. Apple hat seit September 2020 durchgesetzt, dass iOS und macOS keine Zertifikate mit mehr als 398 Tagen Laufzeit akzeptieren. Google Chrome plant, diesen Grenzwert bis 2027 schrittweise auf 90 Tage zu senken, was langfristig Automatisierung erzwingt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-8-zertifikate-inspizieren-und-verifizieren\">Schritt 8: Zertifikate inspizieren und verifizieren<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Das Inspizieren und Verifizieren von Zertifikaten ist eine der h\u00e4ufigsten OpenSSL-Aufgaben im Alltag. Diese Befehle helfen bei der Fehlersuche, der Ablauf\u00fcberwachung und dem Pr\u00fcfen von Zertifikatsketten.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Zertifikat vollst\u00e4ndig anzeigen\nopenssl x509 -in server.crt -text -noout\n\n# Nur spezifische Felder anzeigen\nopenssl x509 -in server.crt -noout -subject -issuer -dates -fingerprint\n\n# Erwartete Ausgabe:\n# subject=C=DE, ST=Bayern, O=MeinUnternehmen GmbH, CN=api.intern.example.com\n# issuer=C=DE, ST=Bayern, O=MeinUnternehmen GmbH, CN=MeinUnternehmen Root CA\n# notBefore=Jun 17 09:00:00 2026 GMT\n# notAfter=Jun 17 09:00:00 2027 GMT\n# SHA256 Fingerprint=A3:7F:2C:...\n\n# Subject Alternative Names separat anzeigen\nopenssl x509 -in server.crt -noout -ext subjectAltName\n\n# Privaten Schl\u00fcssel auf \u00dcbereinstimmung mit Zertifikat pr\u00fcfen\n# (beide md5-Hashes m\u00fcssen identisch sein)\nopenssl x509 -noout -pubkey -in server.crt | openssl md5\nopenssl pkey -pubout -in server.key | openssl md5\n\n# Zertifikat gegen CA mit spezifischem Zweck verifizieren\nopenssl verify -CAfile myCA\/certs\/ca.crt -purpose sslserver server.crt\n\n# Ablaufdatum berechnen (Tage bis Ablauf)\nNOT_AFTER=$(openssl x509 -noout -enddate -in server.crt | cut -d= -f2)\nEND_TS=$(date -d \"$NOT_AFTER\" +%s)\nNOW_TS=$(date +%s)\necho \"Zertifikat l\u00e4uft ab in: $(( (END_TS - NOW_TS) \/ 86400 )) Tagen\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Die Pr\u00fcfung mit <code>-purpose sslserver<\/code> verifiziert nicht nur die Zertifikatskette, sondern auch ob das Zertifikat tats\u00e4chlich f\u00fcr die Serverauthentifizierung geeignet ist. Fehlt die Extension <code>extendedKeyUsage=serverAuth<\/code>, schl\u00e4gt diese Pr\u00fcfung fehl, obwohl <code>openssl verify<\/code> ohne <code>-purpose<\/code> erfolgreich ist. Diese Unterscheidung ist bei der Fehlersuche wichtig.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-9-live-tls-verbindung-testen-und-analysieren\">Schritt 9: Live-TLS-Verbindung testen und analysieren<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Mit <code>openssl s_client<\/code> lassen sich TLS-Verbindungen zu beliebigen Servern testen. Das Tool zeigt die Zertifikatskette, verwendete Cipher Suites, TLS-Protokollversion und Handshake-Details und ist damit ein unverzichtbares Diagnosewerkzeug.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># TLS-Verbindung zu einem \u00f6ffentlichen Server testen\nopenssl s_client -connect example.com:443 -servername example.com -brief\n\n# Nur TLS 1.3 erlauben (schl\u00e4gt fehl, wenn Server kein TLS 1.3 unterst\u00fctzt)\nopenssl s_client -connect example.com:443 -tls1_3 -brief\n\n# Verbindung mit eigener CA verifizieren\nopenssl s_client -connect api.intern.example.com:443 \\\n  -CAfile myCA\/certs\/ca.crt \\\n  -servername api.intern.example.com\n\n# Relevante Ausgabe-Ausz\u00fcge:\n# CONNECTED(00000003)\n# depth=1 C=DE, ST=Bayern, O=MeinUnternehmen GmbH, CN=MeinUnternehmen Root CA\n# verify return:1\n# depth=0 CN=api.intern.example.com\n# verify return:1\n# ---\n# SSL-Session:\n#     Protocol  : TLSv1.3\n#     Cipher    : TLS_AES_256_GCM_SHA384\n# ---\n# Verification: OK\n\n# Zertifikat direkt vom Server herunterladen und pr\u00fcfen\necho | openssl s_client -connect example.com:443 2>\/dev\/null | \\\n  openssl x509 -noout -subject -issuer -dates\n\n# STARTTLS f\u00fcr E-Mail-Server (SMTP Port 587)\nopenssl s_client -connect mail.example.com:587 -starttls smtp\n\n# STARTTLS f\u00fcr IMAP (Port 143)\nopenssl s_client -connect imap.example.com:143 -starttls imap<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Der Subbefehl <code>s_client<\/code> funktioniert mit jedem TLS-f\u00e4higen Protokoll. Mit <code>-starttls smtp<\/code> bzw. <code>-starttls imap<\/code> lassen sich auch E-Mail-Server pr\u00fcfen. Das ist besonders n\u00fctzlich, um zu verifizieren, dass ein frisch ausgestelltes Zertifikat korrekt konfiguriert ist und die vollst\u00e4ndige Zertifikatskette mitgesendet wird. Grundlagen zu TLS 1.3 und dem Handshake-Prozess findest du in <a href=\"\/de\/https-tls-explained\/\">HTTPS und TLS erkl\u00e4rt: Was der Schloss-Button wirklich bedeutet<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-10-wildcard-und-multi-domain-zertifikate\">Schritt 10: Wildcard- und Multi-Domain-Zertifikate<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Wildcard-Zertifikate (z.B. <code>*.example.com<\/code>) decken alle Subdomains einer Ebene ab. Sie sind praktisch f\u00fcr interne Infrastruktur, setzen aber bei \u00f6ffentlichen CAs eine DNS-basierte Validierung voraus. Mit der eigenen CA sind sie problemlos m\u00f6glich. Ein h\u00e4ufiges Missverst\u00e4ndnis: ein Wildcard deckt nur eine Subdomain-Ebene ab.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Konfigurationsdatei f\u00fcr Wildcard + Multi-Domain-Zertifikat\ncat > wildcard-ext.cnf << 'EOF'\n[ v3_req ]\nsubjectAltName = @alt_names\nkeyUsage = critical, digitalSignature, keyEncipherment\nextendedKeyUsage = serverAuth\nbasicConstraints = CA:FALSE\n\n[ alt_names ]\nDNS.1 = example.com\nDNS.2 = *.example.com\nDNS.3 = *.api.example.com\nDNS.4 = intern.example.com\nIP.1 = 10.0.0.1\nIP.2 = 172.16.0.1\nEOF\n\n# Wildcard-Schl\u00fcssel und CSR generieren\nopenssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-384 -out wildcard.key\nopenssl req -new -key wildcard.key -out wildcard.csr \\\n  -subj \"\/C=DE\/ST=Bayern\/O=MeinUnternehmen GmbH\/CN=*.example.com\"\n\n# Mit CA signieren (max. 365 Tage)\nopenssl x509 -req -in wildcard.csr \\\n  -CA myCA\/certs\/ca.crt \\\n  -CAkey myCA\/private\/ca.key \\\n  -passin pass:SICHERES_CA_PASSWORT \\\n  -CAcreateserial \\\n  -out wildcard.crt \\\n  -days 365 \\\n  -extfile wildcard-ext.cnf \\\n  -extensions v3_req\n\n# SAN-Eintr\u00e4ge des ausgestellten Zertifikats pr\u00fcfen\nopenssl x509 -in wildcard.crt -noout -ext subjectAltName\n# Ausgabe:\n# X509v3 Subject Alternative Name:\n#     DNS:example.com, DNS:*.example.com, DNS:*.api.example.com,\n#     DNS:intern.example.com, IP Address:10.0.0.1, IP Address:172.16.0.1<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Einschr\u00e4nkungen von Wildcards:<\/strong> Das Muster <code>*.example.com<\/code> deckt <code>api.example.com<\/code> ab, aber nicht <code>dev.api.example.com<\/code> (zwei Ebenen tiefer). F\u00fcr mehrere Ebenen werden separate Wildcard-Eintr\u00e4ge wie <code>*.api.example.com<\/code> ben\u00f6tigt. Au\u00dferdem deckt der Wildcard nicht die Apex-Domain <code>example.com<\/code> selbst ab, weshalb sie als separater <code>DNS.1<\/code>-Eintrag aufgenommen werden muss.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-11-zertifikatsformate-konvertieren-pem-der-pkcs12\">Schritt 11: Zertifikatsformate konvertieren (PEM, DER, PKCS#12)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In der Praxis existieren verschiedene Zertifikatsformate, die von unterschiedlichen Systemen erwartet werden. Java-Keystores ben\u00f6tigen PKCS#12 (.p12\/.pfx), Windows-Systeme oft DER (.der\/.cer), und Linux-Server arbeiten mit PEM (.pem\/.crt).<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Format<\/th><th>Dateiendung<\/th><th>Encoding<\/th><th>Verwendung<\/th><th>Enth\u00e4lt<\/th><\/tr><\/thead><tbody><tr><td>PEM<\/td><td>.pem, .crt, .key<\/td><td>Base64 (ASCII)<\/td><td>Linux, Apache, Nginx<\/td><td>Zertifikat, Schl\u00fcssel oder beides<\/td><\/tr><tr><td>DER<\/td><td>.der, .cer<\/td><td>Bin\u00e4r (ASN.1)<\/td><td>Windows, Java, iOS<\/td><td>Nur Zertifikat<\/td><\/tr><tr><td>PKCS#12<\/td><td>.pfx, .p12<\/td><td>Bin\u00e4r, verschl\u00fcsselt<\/td><td>Windows, Java, Android, macOS<\/td><td>Zertifikat + Schl\u00fcssel + Chain<\/td><\/tr><tr><td>PKCS#7<\/td><td>.p7b, .p7c<\/td><td>Base64 oder Bin\u00e4r<\/td><td>Windows, Java<\/td><td>Nur Zertifikate (kein Schl\u00fcssel)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<pre class=\"wp-block-code\"><code># PEM zu DER konvertieren\nopenssl x509 -in server.crt -outform DER -out server.der\n\n# DER zu PEM konvertieren\nopenssl x509 -in server.der -inform DER -out server-from-der.crt\n\n# PEM zu PKCS#12 (mit Schl\u00fcssel und CA-Zertifikat)\nopenssl pkcs12 -export \\\n  -in server.crt \\\n  -inkey server.key \\\n  -certfile myCA\/certs\/ca.crt \\\n  -out server.p12 \\\n  -name \"api.intern.example.com\" \\\n  -passout pass:PKCS12_PASSWORT\n\n# PKCS#12 zu PEM (alle Bestandteile)\nopenssl pkcs12 -in server.p12 -passin pass:PKCS12_PASSWORT \\\n  -out server-extracted.pem -nodes\n\n# \u00c4ltere .pfx-Dateien mit Legacy-Algorithmen \u00f6ffnen (OpenSSL 3.x)\nopenssl pkcs12 -legacy -in old-windows.pfx -passin pass:PKCS12_PASSWORT \\\n  -out extracted-legacy.pem -nodes\n\n# Zertifikatskette (fullchain) f\u00fcr Nginx\/Apache erstellen\ncat server.crt myCA\/certs\/ca.crt > fullchain.crt<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"schritt-12-sicherheit-best-practices-und-schluesselverwaltung\">Schritt 12: Sicherheit, Best Practices und Schl\u00fcsselverwaltung<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Die kryptografische St\u00e4rke von OpenSSL h\u00e4ngt nicht nur von den Algorithmen ab, sondern auch von der Sorgfalt bei Konfiguration, Schl\u00fcsselspeicherung und Update-Disziplin. Diese letzten Ma\u00dfnahmen entscheiden \u00fcber die langfristige Sicherheit der gesamten PKI-Infrastruktur.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Korrekte Dateiberechtigungen setzen (unverzichtbar)\nchmod 600 server.key private-ec-p384.key\nchmod 400 myCA\/private\/ca.key  # CA-Schl\u00fcssel: nur lesen, kein Schreiben\nsudo chown root:root myCA\/private\/ca.key\n\n# Berechtigungen \u00fcberpr\u00fcfen\nls -la server.key myCA\/private\/ca.key\n# Korrekte Ausgabe:\n# -rw------- 1 user  user  241 Jun 17 09:00 server.key\n# -r-------- 1 root  root  313 Jun 17 09:00 myCA\/private\/ca.key\n\n# System-weit sichere TLS-Standards erzwingen (openssl.cnf)\n# Pfad pr\u00fcfen:\nopenssl version -d  # zeigt OPENSSLDIR\n\n# Empfohlene Einstellungen in \/usr\/lib\/ssl\/openssl.cnf:\n# [system_default_sect]\n# MinProtocol = TLSv1.2\n# CipherString = DEFAULT@SECLEVEL=2\n# Curves = P-384:P-256:X25519\n\n# Passphrase eines Schl\u00fcssels entfernen (f\u00fcr automatische Dienste)\nopenssl pkey -in encrypted.key -passin pass:PASSWORT -out unencrypted.key\nchmod 600 unencrypted.key\n\n# CA-Zertifikat systemweit als vertrauensw\u00fcrdig eintragen (Ubuntu\/Debian)\nsudo cp myCA\/certs\/ca.crt \/usr\/local\/share\/ca-certificates\/mein-intern-ca.crt\nsudo update-ca-certificates\n# Ausgabe: 1 added, 0 removed; done.\n\n# Test: Curl mit eigener CA ohne explizites --cacert\ncurl https:\/\/api.intern.example.com\/health<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr hochsicherheitskritische Umgebungen sollte der CA-Schl\u00fcssel auf einem Hardware Security Module (HSM) gespeichert werden. G\u00fcnstige Alternativen f\u00fcr kleinere Setups sind YubiKeys (mit OpenPGP- oder PIV-Modul) oder Nitrokeys. OpenSSL unterst\u00fctzt den Zugriff auf PKCS#11-f\u00e4hige HSMs \u00fcber das Engine-Interface (<code>engine pkcs11<\/code> in OpenSSL 3.x).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"haeufige-fallstricke-mit-openssl-zertifikaten\">H\u00e4ufige Fallstricke mit OpenSSL-Zertifikaten<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fallstrick-1-fehlende-subject-alternative-names-san\">Fallstrick 1: Fehlende Subject Alternative Names (SAN)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Seit Chrome 58 (2017) und gem\u00e4\u00df RFC 2818 ignorieren Browser den Common Name (CN) f\u00fcr die Hostnamen-Validierung vollst\u00e4ndig. Nur SANs werden gepr\u00fcft. Symptom in Chrome: <code>NET::ERR_CERT_COMMON_NAME_INVALID<\/code>, in Firefox: <code>SSL_ERROR_BAD_CERT_DOMAIN<\/code>. Das Zertifikat sieht in openssl-Ausgaben korrekt aus, was die Diagnose erschwert. L\u00f6sung: Immer <code>-addext \"subjectAltName=DNS:example.com\"<\/code> verwenden und mit <code>openssl x509 -in cert.crt -noout -ext subjectAltName<\/code> verifizieren.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fallstrick-2-veraltete-openssl-version-im-einsatz\">Fallstrick 2: Veraltete OpenSSL-Version im Einsatz<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">OpenSSL 1.1.1 erh\u00e4lt seit September 2023 keine Sicherheits-Updates mehr, ist jedoch noch auf vielen Ubuntu-20.04-Systemen vorinstalliert. Diese Version ist anf\u00e4llig f\u00fcr alle seit 2023 entdeckten CVEs. Abhilfe: System auf Ubuntu 22.04 oder 24.04 aktualisieren oder OpenSSL 3.x manuell installieren. Pr\u00fcfung: <code>openssl version<\/code>. Sollte mit \"3.x.x\" beginnen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fallstrick-3-privater-schluessel-passt-nicht-zum-zertifikat\">Fallstrick 3: Privater Schl\u00fcssel passt nicht zum Zertifikat<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Nginx und Apache starten nicht, wenn Schl\u00fcssel und Zertifikat nicht zusammenpassen. Fehlermeldung: <code>SSL_CTX_use_PrivateKey_file failed<\/code> oder <code>Private key does not match the certificate public key<\/code>. Diagnose: Die \u00f6ffentlichen Schl\u00fcssel-Hashes m\u00fcssen identisch sein.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># \u00d6ffentliche Schl\u00fcssel beider Dateien vergleichen\nopenssl x509 -noout -pubkey -in server.crt | openssl md5\nopenssl pkey -pubout -in server.key | openssl md5\n# Identische Ausgabe zeigt korrekte Paarung an<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fallstrick-4-zu-lange-zertifikatslaufzeit\">Fallstrick 4: Zu lange Zertifikatslaufzeit<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Apple erzwingt seit September 2020 eine maximale Zertifikatslaufzeit von 398 Tagen. Zertifikate mit l\u00e4ngerer Laufzeit werden auf iOS, macOS und Safari abgelehnt, auch wenn sie von einer g\u00fcltigen CA signiert wurden. Verwende maximal <code>-days 365<\/code> f\u00fcr Serverzertifikate. F\u00fcr Root-CAs sind 20 Jahre (7.300 Tage) akzeptabel, da sie offline aufbewahrt und nicht in Handshakes ausgetauscht werden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fallstrick-5-ca-zertifikat-nicht-als-vertrauenswuerdig-eingetragen\">Fallstrick 5: CA-Zertifikat nicht als vertrauensw\u00fcrdig eingetragen<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Selbst wenn das Zertifikat korrekt von der eigenen CA signiert ist, erscheint im Browser <code>NET::ERR_CERT_AUTHORITY_INVALID<\/code>, solange das CA-Zertifikat nicht im Trust Store des Clients eingetragen ist. Jedes Ger\u00e4t und jeder Browser muss das CA-Zertifikat einmalig importieren. F\u00fcr Unternehmensumgebungen automatisiert Group Policy Object (GPO) unter Windows bzw. MDM-Profile unter macOS\/iOS diesen Prozess.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fallstrick-6-passphrase-geschuetzte-schluessel-blockieren-dienst-neustarts\">Fallstrick 6: Passphrase-gesch\u00fctzte Schl\u00fcssel blockieren Dienst-Neustarts<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Nginx und Apache k\u00f6nnen beim Start nach einer Passphrase fragen. Das verhindert automatische Neustarts nach System-Updates und sorgt f\u00fcr Ausfallzeiten. F\u00fcr Produktivserver sollte der Schl\u00fcssel entweder passphrasenlos sein (mit 600er Dateiberechtigungen) oder ein Secrets-Manager wie HashiCorp Vault die Passphrase automatisch bereitstellen. Passphrase entfernen: <code>openssl pkey -in encrypted.key -passin pass:PASSWORT -out unencrypted.key<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"fallstrick-7-fehlende-oder-falsche-basicconstraints-extension\">Fallstrick 7: Fehlende oder falsche basicConstraints-Extension<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ohne die Extension <code>basicConstraints=CA:FALSE<\/code> in Serverzertifikaten k\u00f6nnten diese theoretisch als CA missbraucht werden. Moderne Browser pr\u00fcfen dies und lehnen Zertifikate ohne korrekte <code>basicConstraints<\/code> ab. CA-Zertifikate ben\u00f6tigen zwingend <code>CA:TRUE<\/code> und <code>keyUsage=keyCertSign<\/code>. Pr\u00fcfung: <code>openssl x509 -in cert.crt -noout -text | grep -A 3 \"Basic Constraints\"<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"troubleshooting-10-haeufige-openssl-fehlermeldungen\">Troubleshooting: 10 h\u00e4ufige OpenSSL-Fehlermeldungen<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Fehlermeldung<\/th><th>Ursache<\/th><th>L\u00f6sung<\/th><\/tr><\/thead><tbody><tr><td><code>unable to load certificate<\/code><\/td><td>Datei nicht gefunden oder falsches Format<\/td><td>Pfad pr\u00fcfen; <code>-inform DER<\/code> bei Bin\u00e4rdateien angeben<\/td><\/tr><tr><td><code>no certificate file found<\/code><\/td><td>Leere PEM-Datei oder falscher MIME-Typ<\/td><td><code>head -1 cert.crt<\/code>: muss <code>-----BEGIN CERTIFICATE-----<\/code> enthalten<\/td><\/tr><tr><td><code>certificate signature failure<\/code><\/td><td>CA-Schl\u00fcssel passt nicht zum CA-Zertifikat<\/td><td>CA-Schl\u00fcsselpaar neu generieren oder korrektes CA.key verwenden<\/td><\/tr><tr><td><code>unable to get local issuer certificate<\/code><\/td><td>Intermediate-CA-Zertifikat fehlt in der Chain<\/td><td>Fullchain erstellen: <code>cat cert.crt intermediate.crt ca.crt &gt; fullchain.crt<\/code><\/td><\/tr><tr><td><code>CERTIFICATE_VERIFY_FAILED<\/code><\/td><td>CA nicht im Trust Store oder Zertifikat abgelaufen<\/td><td>CA-Zertifikat importieren oder neues Zertifikat ausstellen<\/td><\/tr><tr><td><code>no shared cipher<\/code><\/td><td>Keine gemeinsamen Cipher Suites zwischen Client und Server<\/td><td>Minimale TLS-Version und Cipher Suites auf beiden Seiten angleichen<\/td><\/tr><tr><td><code>PKCS12 MAC could not be verified<\/code><\/td><td>Falsches Passwort oder Legacy-Algorithmus<\/td><td>Korrektes Passwort; <code>-legacy<\/code> Flag f\u00fcr alte .pfx-Dateien<\/td><\/tr><tr><td><code>routines::wrong tag<\/code><\/td><td>DER-Datei wird als PEM geladen<\/td><td><code>-inform DER<\/code> explizit angeben<\/td><\/tr><tr><td><code>Error, extension value length mismatch<\/code><\/td><td>Syntaxfehler in der .cnf-Konfigurationsdatei<\/td><td>Konfigurationsdatei Zeile f\u00fcr Zeile pr\u00fcfen; besonders Leerzeichen und Kommas<\/td><\/tr><tr><td><code>Private key does not match the certificate public key<\/code><\/td><td>Falsche Schl\u00fcsseldatei angegeben<\/td><td>\u00d6ffentliche Schl\u00fcssel beider Dateien mit openssl md5 vergleichen<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"vollstaendiges-beispielprojekt-interne-microservice-pki\">Vollst\u00e4ndiges Beispielprojekt: Interne Microservice-PKI<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Das folgende Shell-Skript richtet eine vollst\u00e4ndige interne PKI f\u00fcr eine Microservice-Umgebung ein: Root-CA, Intermediate-CA und drei Serverzertifikate. Das Two-Tier-Modell ist Best Practice: Der Root-CA-Schl\u00fcssel bleibt offline und wird nur zum Signieren der Intermediate-CA genutzt. Bei Kompromittierung der Intermediate-CA kann ohne Neuerstellung der Root-CA eine neue Intermediate ausgestellt werden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n# Vollst\u00e4ndiges PKI-Setup f\u00fcr Microservice-Umgebung\n# Getestet mit OpenSSL 3.5.5 LTS auf Ubuntu 24.04\n\nset -euo pipefail\n\nCA_PASS=\"SICHERES_PASSWORT_HIER_ERSETZEN\"\nPKI_DIR=\".\/pki\"\nSERVICES=(\"api-gateway\" \"postgres-db\" \"grafana\")\nDOMAINS=(\"api.intern\" \"db.intern\" \"metrics.intern\")\n\necho \"[1\/6] Verzeichnisstruktur anlegen...\"\nmkdir -p \"$PKI_DIR\"\/{root-ca\/{certs,private,csr},intermediate\/{certs,private,csr},server}\nchmod 700 \"$PKI_DIR\"\/root-ca\/private \"$PKI_DIR\"\/intermediate\/private\ntouch \"$PKI_DIR\"\/root-ca\/index.txt \"$PKI_DIR\"\/intermediate\/index.txt\necho 1000 > \"$PKI_DIR\"\/root-ca\/serial\necho 2000 > \"$PKI_DIR\"\/intermediate\/serial\n\necho \"[2\/6] Root-CA erstellen (offline aufbewahren)...\"\nopenssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-384 \\\n  -aes-256-cbc -pass pass:\"$CA_PASS\" \\\n  -out \"$PKI_DIR\/root-ca\/private\/root.key\"\nopenssl req -new -x509 -key \"$PKI_DIR\/root-ca\/private\/root.key\" \\\n  -passin pass:\"$CA_PASS\" -out \"$PKI_DIR\/root-ca\/certs\/root.crt\" -days 7300 \\\n  -subj \"\/C=DE\/O=MeinUnternehmen\/CN=Root CA\" \\\n  -addext \"basicConstraints=critical,CA:TRUE,pathlen:1\" \\\n  -addext \"keyUsage=critical,keyCertSign,cRLSign\"\n\necho \"[3\/6] Intermediate-CA erstellen...\"\nopenssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-384 \\\n  -aes-256-cbc -pass pass:\"$CA_PASS\" \\\n  -out \"$PKI_DIR\/intermediate\/private\/inter.key\"\nopenssl req -new -key \"$PKI_DIR\/intermediate\/private\/inter.key\" \\\n  -passin pass:\"$CA_PASS\" -out \"$PKI_DIR\/intermediate\/csr\/inter.csr\" \\\n  -subj \"\/C=DE\/O=MeinUnternehmen\/CN=Intermediate CA\"\nopenssl x509 -req -in \"$PKI_DIR\/intermediate\/csr\/inter.csr\" \\\n  -CA \"$PKI_DIR\/root-ca\/certs\/root.crt\" \\\n  -CAkey \"$PKI_DIR\/root-ca\/private\/root.key\" -passin pass:\"$CA_PASS\" \\\n  -CAcreateserial -out \"$PKI_DIR\/intermediate\/certs\/inter.crt\" -days 1825 \\\n  -extfile <(printf \"[v3]\\nbasicConstraints=critical,CA:TRUE,pathlen:0\\nkeyUsage=critical,keyCertSign,cRLSign\") \\\n  -extensions v3\n\necho \"[4\/6] Serverzertifikate fuer alle Services erstellen...\"\nfor i in \"${!SERVICES[@]}\"; do\n  SVC=\"${SERVICES[$i]}\"\n  DOM=\"${DOMAINS[$i]}\"\n  openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-384 \\\n    -out \"$PKI_DIR\/server\/$SVC.key\"\n  openssl req -new -key \"$PKI_DIR\/server\/$SVC.key\" \\\n    -out \"$PKI_DIR\/server\/$SVC.csr\" \\\n    -subj \"\/C=DE\/O=MeinUnternehmen\/CN=$DOM\"\n  openssl x509 -req -in \"$PKI_DIR\/server\/$SVC.csr\" \\\n    -CA \"$PKI_DIR\/intermediate\/certs\/inter.crt\" \\\n    -CAkey \"$PKI_DIR\/intermediate\/private\/inter.key\" -passin pass:\"$CA_PASS\" \\\n    -CAcreateserial -out \"$PKI_DIR\/server\/$SVC.crt\" -days 365 \\\n    -extfile <(printf \"[v3]\\nsubjectAltName=DNS:%s,DNS:%s\\nbasicConstraints=CA:FALSE\\nkeyUsage=critical,digitalSignature\\nextendedKeyUsage=serverAuth\" \"$DOM\" \"$SVC\") \\\n    -extensions v3\n  echo \"  OK: $SVC ($DOM)\"\ndone\n\necho \"[5\/6] Vollstaendige Zertifikatskette erstellen...\"\ncat \"$PKI_DIR\/intermediate\/certs\/inter.crt\" \\\n    \"$PKI_DIR\/root-ca\/certs\/root.crt\" > \"$PKI_DIR\/fullchain-ca.crt\"\n\necho \"[6\/6] Alle Serverzertifikate verifizieren...\"\nfor SVC in \"${SERVICES[@]}\"; do\n  openssl verify -CAfile \"$PKI_DIR\/fullchain-ca.crt\" \"$PKI_DIR\/server\/$SVC.crt\"\ndone\n\necho \"\"\necho \"PKI-Setup abgeschlossen!\"\necho \"CA-Zertifikat fuer Trust-Store-Import: $PKI_DIR\/root-ca\/certs\/root.crt\"\necho \"Root-CA-Schluessel JETZT offline sichern: $PKI_DIR\/root-ca\/private\/root.key\"\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"openssl-sicherheitsluecken-2025-2026-kritische-cves-im-ueberblick\">OpenSSL-Sicherheitsl\u00fccken 2025\/2026: Kritische CVEs im \u00dcberblick<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">OpenSSL war in den letzten 12 Monaten Ziel mehrerer schwerwiegender Sicherheitsl\u00fccken. Die vollst\u00e4ndige CVE-Liste wird unter <a href=\"https:\/\/www.openssl.org\/news\/vulnerabilities.html\" rel=\"noopener noreferrer\" target=\"_blank\">openssl.org\/news\/vulnerabilities.html<\/a> gepflegt.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>CVE<\/th><th>Schweregrad<\/th><th>Betroffene Versionen<\/th><th>Typ<\/th><th>Fix<\/th><\/tr><\/thead><tbody><tr><td>CVE-2025-15467<\/td><td><strong>High (RCE)<\/strong><\/td><td>3.0 bis 3.6<\/td><td>Stack-Buffer-Overflow in CMS AuthEnvelopedData, pre-auth<\/td><td>3.5.5+<\/td><\/tr><tr><td>CVE-2025-11187<\/td><td>Moderate<\/td><td>3.4, 3.5, 3.6<\/td><td>Stack-Buffer-Overflow in PKCS#12 MAC-Verifizierung<\/td><td>3.5.5+<\/td><\/tr><tr><td>CVE-2025-15468<\/td><td>High<\/td><td>3.x mit QUIC<\/td><td>NULL-Pointer-Dereferenz im QUIC-Handler (DoS)<\/td><td>3.5.5+<\/td><\/tr><tr><td>CVE-2025-66199<\/td><td>High<\/td><td>3.x<\/td><td>\u00dcberm\u00e4\u00dfige Speicherzuweisung in TLS-1.3-Zertifikatskomprimierung (DoS)<\/td><td>3.5.5+<\/td><\/tr><tr><td>CVE-2026-42766<\/td><td>High<\/td><td>vor 3.5<\/td><td>NULL-Dereferenz in CMS-Entschl\u00fcsselung<\/td><td>3.5+<\/td><\/tr><tr><td>CVE-2026-45446<\/td><td>High<\/td><td>vor 3.5<\/td><td>Falsches Tag-Processing in AES-GCM-SIV f\u00fcr leere Nachrichten<\/td><td>3.5+<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">CVE-2025-15467 ist besonders kritisch: Es handelt sich um einen pre-auth ausnutzbaren RCE-Fehler in der AEAD-Parsing-Logik. Alle Systeme mit OpenSSL 3.0 bis 3.6 sind betroffen und sollten sofort auf 3.5.5 aktualisiert werden. Das Update ist \u00fcber den Paketmanager verf\u00fcgbar: <code>sudo apt update && sudo apt upgrade openssl<\/code>. Nach dem Update den Dienst neu starten, der OpenSSL nutzt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Post-Quantum-Kryptografie: OpenSSL 3.5+ unterst\u00fctzt ML-KEM (CRYSTALS-Kyber, f\u00fcr Schl\u00fcsselaustausch) und ML-DSA (CRYSTALS-Dilithium, f\u00fcr Signaturen) als experimentelle Algorithmen. Sie ersetzen langfristig RSA und ECDSA gegen Quantencomputer-Angriffe. Mehr dazu in <a href=\"\/de\/ml-kem-kyber-nodejs\/\">ML-KEM (Kyber) in Node.js: Post-Quantum-Kryptografie in 12 Schritten [2026]<\/a> und <a href=\"\/de\/post-quantum-cryptography-2026\/\">Post-Quantum-Kryptografie: 50% des Webs jetzt sicher [2026]<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die technische Spezifikation f\u00fcr TLS 1.3, den Protokollstandard hinter HTTPS, ist als <a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/rfc8446\" rel=\"noopener noreferrer\" target=\"_blank\">RFC 8446 bei der IETF<\/a> frei zug\u00e4nglich. Die vollst\u00e4ndige Dokumentation aller OpenSSL-3.5-Befehle findet sich in der <a href=\"https:\/\/www.openssl.org\/docs\/man3.5\/\" rel=\"noopener noreferrer\" target=\"_blank\">offiziellen OpenSSL-3.5-Manpage<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"fortgeschrittene-themen-ocsp-crl-und-zertifikatswiderruf\">Fortgeschrittene Themen: OCSP, CRL und Zertifikatswiderruf<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr produktive PKI-Infrastrukturen reicht es nicht, Zertifikate nur auszustellen. Kompromittierte oder fehlerhaft ausgestellte Zertifikate m\u00fcssen widerrufbar sein, bevor sie ablaufen. Daf\u00fcr gibt es zwei Mechanismen: Certificate Revocation Lists (CRL) und Online Certificate Status Protocol (OCSP). Beide sind komplement\u00e4r, haben aber unterschiedliche Eigenschaften.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>CRL (Certificate Revocation List):<\/strong> Eine CRL ist eine regelm\u00e4\u00dfig aktualisierte, von der CA signierte Liste von Seriennummern widerrufener Zertifikate. Clients laden die CRL periodisch herunter und pr\u00fcfen lokal, ob ein Zertifikat widerrufen ist. Nachteil: Die CRL kann gro\u00df werden und ist nur so aktuell wie die letzte Distribution.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>OCSP (Online Certificate Status Protocol):<\/strong> OCSP erm\u00f6glicht eine Echtzeit-Abfrage des Zertifikatsstatus direkt beim OCSP-Responder der CA. Clients senden die Seriennummer und erhalten eine signierte Antwort (\"good\", \"revoked\" oder \"unknown\"). OCSP-Stapling ist eine Optimierung: Der Webserver fragt selbst den OCSP-Status ab und sendet die signierte Antwort im TLS-Handshake mit, was Client-Anfragen an den OCSP-Responder eliminiert.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Schritt 1: CRL-Seriennummer initialisieren\necho 1000 > myCA\/crlnumber\n\n# Schritt 2: Leere initiale CRL erstellen\n# (openssl.cnf muss [CA_default] mit dir, database, serial, crlnumber konfiguriert haben)\nopenssl ca -gencrl \\\n  -keyfile myCA\/private\/ca.key \\\n  -cert myCA\/certs\/ca.crt \\\n  -passin pass:SICHERES_CA_PASSWORT \\\n  -out myCA\/crl\/ca.crl \\\n  -crldays 30\n\n# CRL-Inhalt anzeigen\nopenssl crl -in myCA\/crl\/ca.crl -text -noout\n\n# Schritt 3: Zertifikat widerrufen\nopenssl ca -revoke server.crt \\\n  -keyfile myCA\/private\/ca.key \\\n  -cert myCA\/certs\/ca.crt \\\n  -passin pass:SICHERES_CA_PASSWORT \\\n  -reason keyCompromise\n\n# Schritt 4: CRL nach Widerruf aktualisieren\nopenssl ca -gencrl -keyfile myCA\/private\/ca.key \\\n  -cert myCA\/certs\/ca.crt -passin pass:SICHERES_CA_PASSWORT \\\n  -out myCA\/crl\/ca.crl -crldays 30\n\n# OCSP-Abfrage gegen externen Server (z.B. Let's Encrypt)\necho | openssl s_client -connect example.com:443 2>\/dev\/null | \\\n  openssl x509 -noout -ocsp_uri\n# Gibt die OCSP-Responder-URL des Zertifikats aus\n\n# OCSP-Status direkt abfragen\nOCSP_URL=$(echo | openssl s_client -connect example.com:443 2>\/dev\/null | \\\n  openssl x509 -noout -ocsp_uri)\necho | openssl s_client -connect example.com:443 2>\/dev\/null > \/tmp\/cert.pem\nopenssl ocsp -issuer \/etc\/ssl\/certs\/ISRG_Root_X1.pem \\\n  -cert \/tmp\/cert.pem -url \"$OCSP_URL\" -resp_text -noverify 2>\/dev\/null | head -5<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr Nginx l\u00e4sst sich OCSP-Stapling mit zwei Direktiven aktivieren: <code>ssl_stapling on;<\/code> und <code>ssl_stapling_verify on;<\/code>. Nginx fragt dann im Hintergrund den OCSP-Responder ab und sendet die gecachte Antwort im Handshake mit. Das reduziert die Latenz f\u00fcr Clients und sch\u00fctzt deren Privatsph\u00e4re, weil keine OCSP-Anfragen an externe Server n\u00f6tig sind.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"openssl-in-automatisierungs-pipelines-monitoring-und-zertifikatsablauf\">OpenSSL in Automatisierungs-Pipelines: Monitoring und Zertifikatsablauf<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Abgelaufene Zertifikate sind einer der h\u00e4ufigsten Gr\u00fcnde f\u00fcr ungeplante Ausf\u00e4lle. In einer Infrastruktur mit mehreren Zertifikaten ist manuelles Monitoring schnell fehleranf\u00e4llig. Das folgende Skript pr\u00fcft alle Zertifikate in einem Verzeichnis auf ihr Ablaufdatum und gibt eine Warnung bei weniger als 30 Tagen aus.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\n# Zertifikats-Ablauf-Monitor f\u00fcr alle .crt-Dateien im angegebenen Verzeichnis\n# Verwendung: .\/cert-monitor.sh \/etc\/ssl\/certs \/path\/to\/server-certs\n\nWARN_DAYS=30\nEXIT_CODE=0\n\nfor CERT_DIR in \"$@\"; do\n  echo \"=== Pr\u00fcfe Zertifikate in $CERT_DIR ===\"\n  for CERT in \"$CERT_DIR\"\/*.crt \"$CERT_DIR\"\/*.pem; do\n    [ -f \"$CERT\" ] || continue\n    NOT_AFTER=$(openssl x509 -noout -enddate -in \"$CERT\" 2>\/dev\/null | cut -d= -f2)\n    [ -z \"$NOT_AFTER\" ] && continue\n    END_TS=$(date -d \"$NOT_AFTER\" +%s 2>\/dev\/null) || continue\n    NOW_TS=$(date +%s)\n    DAYS_LEFT=$(( (END_TS - NOW_TS) \/ 86400 ))\n    SUBJECT=$(openssl x509 -noout -subject -in \"$CERT\" 2>\/dev\/null | sed 's\/subject=\/\/')\n\n    if [ \"$DAYS_LEFT\" -le 0 ]; then\n      echo \"KRITISCH: $CERT ($SUBJECT) ist abgelaufen!\"\n      EXIT_CODE=2\n    elif [ \"$DAYS_LEFT\" -le \"$WARN_DAYS\" ]; then\n      echo \"WARNUNG: $CERT ($SUBJECT) l\u00e4uft in $DAYS_LEFT Tagen ab\"\n      EXIT_CODE=1\n    else\n      echo \"OK: $CERT ($SUBJECT) - noch $DAYS_LEFT Tage\"\n    fi\n  done\ndone\n\nexit $EXIT_CODE<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Dieses Skript l\u00e4sst sich direkt als Nagios\/Icinga-Check, als Cron-Job mit E-Mail-Alert oder als Prometheus-Exporter (\u00fcber textfile collector) einsetzen. F\u00fcr gr\u00f6\u00dfere Infrastrukturen empfehlen sich spezialisierte Tools wie <code>certbot renew --dry-run<\/code> f\u00fcr Let's Encrypt, Vault PKI Secrets Engine von HashiCorp oder cert-manager f\u00fcr Kubernetes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Eine weitere wichtige Automatisierung ist die automatische Zertifikatserneuerung. F\u00fcr interne CAs l\u00e4sst sich ein Cron-Job einrichten, der 30 Tage vor Ablauf ein neues Zertifikat ausstellt, den Dienst neu konfiguriert und bei Nginx\/Apache einen sanften Reload ausl\u00f6st (<code>nginx -s reload<\/code>). Das ganze Ecosystem von ACME-Protokoll und automatischer Erneuerung wird im Artikel <a href=\"\/de\/nginx-reverse-proxy-https-einrichten\/\">Nginx Reverse Proxy: HTTPS in 12 Schritten konfigurieren [2026]<\/a> am Produktionsbeispiel gezeigt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"openssl-als-krypto-labor-hashing-verschluesselung-und-signaturen\">OpenSSL als Krypto-Labor: Hashing, Verschl\u00fcsselung und Signaturen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Neben Zertifikaten bietet OpenSSL auch direkte Krypto-Funktionen f\u00fcr den Einsatz in Skripten und Pipelines: symmetrische Verschl\u00fcsselung, Hash-Berechnung und digitale Signaturen. Diese Befehle sind n\u00fctzlich f\u00fcr Datei-Verschl\u00fcsselung, Integrit\u00e4tspr\u00fcfungen und schnelle Tests.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Datei mit AES-256-CBC verschl\u00fcsseln (passwortbasiert)\nopenssl enc -aes-256-cbc -pbkdf2 -iter 100000 \\\n  -in geheime-daten.txt -out geheime-daten.enc \\\n  -pass pass:SICHERES_PASSWORT\n\n# Verschl\u00fcsselte Datei entschl\u00fcsseln\nopenssl enc -aes-256-cbc -pbkdf2 -iter 100000 -d \\\n  -in geheime-daten.enc -out geheime-daten-entschl\u00fcsselt.txt \\\n  -pass pass:SICHERES_PASSWORT\n\n# SHA-256 Hash einer Datei berechnen\nopenssl dgst -sha256 datei.iso\n# Ausgabe: SHA2-256(datei.iso)= a3f7b2...\n\n# HMAC-SHA256 mit Schl\u00fcssel berechnen\necho -n \"Nachrichteninhalt\" | openssl dgst -sha256 -hmac \"GEHEIMER_SCHLUESSEL\"\n\n# Datei mit privatem Schl\u00fcssel signieren (ECDSA)\nopenssl dgst -sha384 -sign private-ec-p384.key \\\n  -out datei.sig datei.txt\n\n# Signatur mit \u00f6ffentlichem Schl\u00fcssel verifizieren\nopenssl dgst -sha384 -verify public-ec-p384.key \\\n  -signature datei.sig datei.txt\n# Ausgabe bei Erfolg: Verified OK\n\n# Zuf\u00e4llige Bytes generieren (f\u00fcr Schl\u00fcssel, Tokens, Salts)\nopenssl rand -hex 32   # 32 Byte = 64 Hex-Zeichen (256-Bit-Token)\nopenssl rand -base64 32  # 32 Byte als Base64 (f\u00fcr Passw\u00f6rter\/Secrets)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Der Befehl <code>openssl rand -hex 32<\/code> ist eine schnelle M\u00f6glichkeit, kryptografisch sichere Zufallswerte zu generieren, z.B. f\u00fcr API-Tokens, Session-Secrets oder Datenbankpassw\u00f6rter. Die zugrundeliegende Entropiequelle ist das Betriebssystem (<code>\/dev\/urandom<\/code> auf Linux), das durch Kernel-interne Hardware-Entropie (CPU-Rauschen, Mausbewegungen) gespeist wird.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Details zu HMAC-SHA256 und dessen Implementierung in Node.js-Anwendungen f\u00fcr API-Authentifizierung findest du im Artikel <a href=\"\/de\/hmac-sha256-nodejs\/\">HMAC-SHA256 in Node.js: 10 Schritte [2026]<\/a>. F\u00fcr AES-256-Verschl\u00fcsselung in JavaScript-Anwendungen empfehle ich <a href=\"\/de\/aes-256-encryption-nodejs\/\">AES-256-Verschl\u00fcsselung in Node.js: 12 Schritte [2026]<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"weiterfuehrende-ressourcen\">Weiterf\u00fchrende Ressourcen<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"verwandte-artikel-auf-shattered-io\">Verwandte Artikel auf shattered.io<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/de\/lets-encrypt-zertifikat-einrichten\/\">Let's Encrypt: Kostenloses TLS-Zertifikat in 12 Schritten einrichten [2026]<\/a><\/li>\n<li><a href=\"\/de\/nginx-reverse-proxy-https-einrichten\/\">Nginx Reverse Proxy: HTTPS in 12 Schritten konfigurieren [2026]<\/a><\/li>\n<li><a href=\"\/de\/rsa-encryption-nodejs\/\">RSA-Verschl\u00fcsselung in Node.js: 11 Schritte [2026]<\/a><\/li>\n<li><a href=\"\/de\/aes-256-encryption-nodejs\/\">AES-256-Verschl\u00fcsselung in Node.js: 12 Schritte [2026]<\/a><\/li>\n<li><a href=\"\/de\/ml-kem-kyber-nodejs\/\">ML-KEM (Kyber) in Node.js: Post-Quantum-Kryptografie in 12 Schritten [2026]<\/a><\/li>\n<li><a href=\"\/de\/https-tls-explained\/\">HTTPS und TLS erkl\u00e4rt: Was der Schloss-Button wirklich bedeutet<\/a><\/li>\n<li><a href=\"\/de\/post-quantum-cryptography-2026\/\">Post-Quantum-Kryptografie: 50% des Webs jetzt sicher [2026]<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"faq-openssl-zertifikate-und-schluessel\">FAQ: OpenSSL-Zertifikate und Schl\u00fcssel<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"was-ist-der-unterschied-zwischen-openssl-3-5-lts-und-4-0-0\">Was ist der Unterschied zwischen OpenSSL 3.5 LTS und 4.0.0?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">OpenSSL 3.5.5 ist die Long-Term-Support-Version mit Support bis April 2030. Sie ist f\u00fcr Produktivumgebungen empfohlen und enth\u00e4lt keine inkompatiblen API-\u00c4nderungen gegen\u00fcber 3.4. OpenSSL 4.0.0 (ver\u00f6ffentlicht April 2026) bringt inkompatible \u00c4nderungen, entfernt alle veralteten Low-Level-Funktionen und f\u00fcgt Post-Quantum-Algorithmen (ML-KEM, ML-DSA) als vollst\u00e4ndig unterst\u00fctzte Features hinzu. Version 4.0.0 eignet sich f\u00fcr neue Projekte mit explizitem PQC-Bedarf, setzt aber aufw\u00e4ndige Migrationstests voraus, da veraltete API-Aufrufe zu Kompilierungsfehlern f\u00fchren.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"wie-lange-sollten-verschiedene-zertifikatstypen-gueltig-sein\">Wie lange sollten verschiedene Zertifikatstypen g\u00fcltig sein?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Root-CA-Zertifikate: 20 Jahre (7.300 Tage), da sie offline aufbewahrt werden und nicht in TLS-Handshakes erscheinen. Intermediate-CA-Zertifikate: 5 Jahre (1.825 Tage). Serverzertifikate: maximal 365 Tage (398 Tage ist das technische Maximum durch Apple). Ab 2027 plant Google Chrome, die maximale Laufzeit f\u00fcr \u00f6ffentlich vertrauensw\u00fcrdige Zertifikate auf 90 Tage zu reduzieren, was Automatisierung wie Let's Encrypt certbot unumg\u00e4nglich macht.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"ecdsa-p-256-oder-rsa-4096-fuer-neue-serverzertifikate\">ECDSA P-256 oder RSA 4096 f\u00fcr neue Serverzertifikate?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">ECDSA P-384 (oder P-256 f\u00fcr maximale Kompatibilit\u00e4t) ist die bessere Wahl f\u00fcr neue Deployments. Die Gr\u00fcnde: kleinere Schl\u00fcssel und Signaturen (96 Byte bei P-384 vs. 512 Byte bei RSA 4096), schnellerer TLS-Handshake, bessere Performance auf Mobilger\u00e4ten und volle TLS-1.3-Kompatibilit\u00e4t. RSA 4096 ist nur sinnvoll, wenn Legacy-Clients ohne EC-Unterst\u00fctzung bedient werden m\u00fcssen, was heutzutage selten vorkommt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"was-ist-der-unterschied-zwischen-pem-und-der\">Was ist der Unterschied zwischen PEM und DER?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">PEM (Privacy Enhanced Mail) ist Base64-kodiertes DER mit Header- und Footer-Zeilen (<code>-----BEGIN CERTIFICATE-----<\/code> \/ <code>-----END CERTIFICATE-----<\/code>). DER ist das bin\u00e4re ASN.1-Encoding. PEM ist das Format der Wahl auf Linux\/Unix-Systemen, da es lesbar und in Textdateien einbettbar ist. DER wird von Java-Keystores, Windows CryptoAPI und \u00e4lteren Systemen erwartet. OpenSSL konvertiert zwischen beiden mit <code>-inform\/-outform DER\/PEM<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"was-tun-bei-pkcs12-mac-could-not-be-verified\">Was tun bei \"PKCS12 MAC could not be verified\"?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Diese Fehlermeldung tritt auf, wenn das Passwort falsch ist oder wenn eine \u00e4ltere .pfx-Datei mit veralteten Legacy-Algorithmen (RC2-40-CBC f\u00fcr den MAC) vorliegt. In OpenSSL 3.x m\u00fcssen Legacy-Dateien mit dem Flag <code>-legacy<\/code> ge\u00f6ffnet werden: <code>openssl pkcs12 -legacy -in old-file.pfx -passin pass:PASSWORT -out extracted.pem -nodes<\/code>. Die Legacy-Algorithmen sind in OpenSSL 3.x standardm\u00e4\u00dfig deaktiviert, weil sie als schwach eingestuft sind.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"wie-pruefe-ich-ob-ein-server-tls-1-3-unterstuetzt\">Wie pr\u00fcfe ich, ob ein Server TLS 1.3 unterst\u00fctzt?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Mit dem Befehl <code>openssl s_client -connect server.example.com:443 -tls1_3 -brief 2&gt;&amp;1 | grep Protocol<\/code>. Gibt die Verbindung <code>Protocol: TLSv1.3<\/code> zur\u00fcck, unterst\u00fctzt der Server TLS 1.3. Schl\u00e4gt sie mit <code>no protocols available<\/code> oder <code>ssl handshake failure<\/code> fehl, ist TLS 1.3 nicht aktiviert oder der Server nutzt eine veraltete OpenSSL-Version (vor 1.1.1). Nginx aktiviert TLS 1.3 \u00fcber <code>ssl_protocols TLSv1.2 TLSv1.3;<\/code> in der Konfiguration.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"koennen-selbstsignierte-zertifikate-sicher-sein\">K\u00f6nnen selbstsignierte Zertifikate sicher sein?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Kryptografisch sind selbstsignierte Zertifikate genauso stark wie CA-signierte. Das Problem ist das Vertrauensmodell: Browser vertrauen nur Zertifikaten von CAs in ihrem Trust Store. Ein selbstsigniertes Zertifikat kann von jedem erstellt werden und bietet deshalb keine Identit\u00e4tsgarantie ohne manuellen Trust-Store-Eintrag. F\u00fcr interne Dienste, bei denen du das CA-Zertifikat selbst an alle Clients verteilst, sind sie vollst\u00e4ndig geeignet. F\u00fcr \u00f6ffentliche Dienste ist Let's Encrypt die bessere Wahl, da kein manueller Trust-Eintrag n\u00f6tig ist.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"was-ist-der-unterschied-zwischen-openssl-req-und-openssl-x509\">Was ist der Unterschied zwischen openssl req und openssl x509?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>openssl req<\/code> verarbeitet PKCS#10 Certificate Signing Requests (CSRs) und kann damit sowohl CSRs erstellen als auch selbstsignierte Zertifikate ausstellen. <code>openssl x509<\/code> verarbeitet fertige X.509-Zertifikate, zeigt ihren Inhalt an, konvertiert Formate und kann CSRs signieren (als vereinfachter CA-Befehl ohne die volle Infrastruktur von <code>openssl ca<\/code>). F\u00fcr die meisten Anwendungsf\u00e4lle ist <code>openssl x509 -req<\/code> zum Signieren ausreichend. Der komplexere Befehl <code>openssl ca<\/code> bietet zus\u00e4tzlich automatische Seriennummern-Verwaltung, Datenbankf\u00fchrung und CRL-Support.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>OpenSSL ist das meistgenutzte Kryptografie-Toolkit der Welt und bildet das Fundament f\u00fcr HTTPS, VPNs, E-Mail-Verschl\u00fcsselung und digitale Zertifikate. Version 3.5.5 LTS (Long-Term-Support bis April 2030) ist der empfohlene Stand f\u00fcr\u2026<\/p>\n","protected":false},"author":8,"featured_media":178,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-177","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cryptography"],"_links":{"self":[{"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/posts\/177","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/comments?post=177"}],"version-history":[{"count":1,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/posts\/177\/revisions"}],"predecessor-version":[{"id":179,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/posts\/177\/revisions\/179"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/media\/178"}],"wp:attachment":[{"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/media?parent=177"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/categories?post=177"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/shattered.io\/de\/wp-json\/wp\/v2\/tags?post=177"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}