Zum Inhalt springen
ecdsa.com

Selbstsignierte vs. CA-signierte Zertifikate: wann welche

Beide verschlüsseln gleich gut. Der Unterschied liegt darin, wer sich für den Schlüssel verbürgt, wie Clients lernen, ihm zu vertrauen, und was kaputtgeht, wenn du ihn rotierst.

Bei selbstsignierten vs. CA-signierten Zertifikaten geht es um die Frage, wer sich für die Bindung zwischen einem öffentlichen Schlüssel und einem Namen verbürgt. Ein selbstsigniertes Zertifikat ist mit seinem eigenen Schlüssel signiert und beweist daher nur, dass sein Inhaber diesen Schlüssel besitzt; ein Client vertraut ihm nur, wenn er angewiesen wurde, genau diesem Zertifikat zu vertrauen. Ein CA-signiertes Zertifikat ist von einer Zertifizierungsstelle signiert, deren Root-Zertifikat der Client bereits vertraut: von einer öffentlichen CA für das Internet oder von einer privaten CA, die du selbst betreibst und verteilst.

Auf einen Blick

SelbstsigniertPrivate CAÖffentliche CA
Wer das Leaf-Zertifikat signiertDer eigene Schlüssel des Leaf-ZertifikatsDeine Root- oder Zwischen-CAEine CA aus den Root Stores von Browsern und Betriebssystemen
Wie Clients lernen, dem Zertifikat zu vertrauenJeder Client pinnt oder installiert genau dieses ZertifikatEin Root-Zertifikat installieren (MDM, Konfigurationsmanagement, Container-Image)Standardmäßig bereits vertrauenswürdig
Rotation des Leaf-ZertifikatsJeder Client muss aktualisiert werdenFür Clients unbemerktFür Clients unbemerkt
WiderrufKeiner; Zertifikat aus jedem Client entfernenEigene CRL, OCSP oder kurze LaufzeitenVon der CA veröffentlichte CRLs
Mögliche NamenBeliebigeAlle, auf die das Root-Zertifikat beschränkt istNur öffentliche Domainnamen und öffentliche IP-Adressen
LaufzeitgrenzenKeine durch Browser; Apple-Plattformen begrenzen TLS-Zertifikate, die seit Juli 2019 ausgestellt wurden, auf 825 TageDieselbe Obergrenze von 825 Tagen auf Apple-PlattformenDerzeit 200 Tage, ab März 2029 47 Tage
Certificate TransparencyNicht protokolliertNicht protokolliertÖffentlich protokolliert, einschließlich jedes Hostnamens
Kosten und AufwandAnfangs keine; hoch bei jeder RotationBetrieb der CA, Schutz ihres SchlüsselsKostenlos mit ACME; erfordert DNS- oder HTTP-Validierung
Typische Toolsopenssl req -x509, mkcert für die lokale Entwicklungstep-ca, HashiCorp Vault PKI, private CAs von Cloud-Anbietern, cert-managerLet's Encrypt und andere ACME-CAs

Wie Clients entscheiden, einem Zertifikat zu vertrauen

Die Pfadvalidierung (RFC 5280 §6) baut eine Kette vom Zertifikat des Servers bis zu einem Vertrauensanker im Root Store des Clients auf und prüft unterwegs bei jedem Glied Signatur, Gültigkeitszeitraum, Basic Constraints, Key Usage und Name Constraints. Ein selbstsigniertes Zertifikat hat denselben Aussteller und dasselbe Subject und ist mit seinem eigenen Schlüssel signiert; die einzige mögliche Kette ist also das Zertifikat selbst. Die Validierung gelingt nur, wenn dieses Zertifikat selbst für den Client ein Vertrauensanker ist – und genau das bedeutet es, ein selbstsigniertes Zertifikat zu „pinnen“ oder zu „installieren“.

Ein CA-signiertes Leaf-Zertifikat ist von einer Zwischen-CA signiert, die ihrerseits zu einer Root-CA führt. Der Client muss das Leaf-Zertifikat nie im Voraus kennen; er braucht nur das Root-Zertifikat. Erst diese Indirektion macht Rotation, Widerruf und Automatisierung möglich.

Das folgende Skript, ausgeführt mit OpenSSL 3.6.5, erzeugt ein selbstsigniertes Zertifikat, eine private Root-CA, die auf Namen unter .internal beschränkt ist, und zwei von dieser Root-CA signierte Leaf-Zertifikate.

Selbstsigniertes Zertifikat, private CA und Name Constraints
#!/bin/sh
dir=$(mktemp -d)
cd "$dir" || exit 1
P256="-newkey ec -pkeyopt ec_paramgen_curve:P-256 -noenc"

# 1. Self-signed server certificate
openssl req -x509 $P256 -keyout self.key -out self.pem -days 30 \
  -subj "/CN=dev.internal" \
  -addext "subjectAltName=DNS:dev.internal,IP:127.0.0.1" \
  -addext "basicConstraints=critical,CA:FALSE" 2>/dev/null
openssl verify self.pem
openssl verify -CAfile self.pem self.pem

# 2. Private root CA limited to .internal names
openssl req -x509 $P256 -keyout ca.key -out ca.pem -days 3650 \
  -subj "/CN=Example Internal Root" \
  -addext "keyUsage=critical,keyCertSign,cRLSign" \
  -addext "nameConstraints=critical,permitted;DNS:.internal" 2>/dev/null

# 3. Two server certificates signed by that CA
for name in api.internal www.example.com; do
  openssl req -x509 $P256 -CA ca.pem -CAkey ca.key -keyout "$name.key" \
    -out "$name.pem" -days 90 -subj "/CN=$name" \
    -addext "subjectAltName=DNS:$name" \
    -addext "basicConstraints=critical,CA:FALSE" \
    -addext "extendedKeyUsage=serverAuth" 2>/dev/null
done
openssl verify api.internal.pem
openssl verify -CAfile ca.pem api.internal.pem
openssl verify -CAfile ca.pem www.example.com.pem
cd / && rm -rf "$dir"
Ausgabe
CN=dev.internal
error 18 at 0 depth lookup: self-signed certificate
error self.pem: verification failed
self.pem: OK
CN=api.internal
error 20 at 0 depth lookup: unable to get local issuer certificate
error api.internal.pem: verification failed
api.internal.pem: OK
CN=www.example.com
error 47 at 0 depth lookup: permitted subtree violation
error www.example.com.pem: verification failed

Das selbstsignierte Zertifikat besteht die Prüfung nur, wenn es als sein eigener Vertrauensanker übergeben wird. Das Leaf-Zertifikat der privaten CA besteht sie, sobald dem Root-Zertifikat vertraut wird, und die Name Constraints der Root-CA hindern sie daran, sich für www.example.com zu verbürgen; das begrenzt den Schaden, falls der CA-Schlüssel jemals missbraucht wird. Beachte, dass openssl req -x509 Zertifikate über seine Konfigurationsdatei standardmäßig als CA kennzeichnet; das explizite CA:FALSE verhindert, dass sich das selbstsignierte Serverzertifikat als Aussteller verwenden lässt.

Was Clients melden, wenn sie dem Zertifikat nicht vertrauen

Wir haben fünf Clients gegen einen lokalen Server getestet, der nacheinander beide Zertifikate präsentierte, ohne ihren Trust Stores etwas hinzuzufügen (20. Oktober 2026, macOS).

ClientSelbstsigniertes ZertifikatLeaf-Zertifikat einer nicht vertrauenswürdigen privaten CA
Node.js 26.10DEPTH_ZERO_SELF_SIGNED_CERTUNABLE_TO_VERIFY_LEAF_SIGNATURE
Python 3.14 (OpenSSL 3.6.5)certificate verify failed: self-signed certificatecertificate verify failed: unable to get local issuer certificate
Go 1.25 (Verifizierer von macOS)x509: certificate signed by unknown authorityx509: “localhost” certificate is not trusted
curl 8.7.1 (LibreSSL)(60) SSL certificate problem: self signed certificate(60) SSL certificate problem: unable to get local issuer certificate
OpenSSL 3.6.5 s_clientVerify return code: 18 (self-signed certificate)Verify return code: 20 (unable to get local issuer certificate)

Browser zeigen NET::ERR_CERT_AUTHORITY_INVALID (Chrome) oder MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT (Firefox). Die Lösung ist nie, die Prüfung abzuschalten (NODE_TLS_REJECT_UNAUTHORIZED=0, verify=False, InsecureSkipVerify, curl -k): Damit entfällt die Authentifizierung für jede Verbindung, die der Prozess aufbaut. Gib dem Client stattdessen das Zertifikat oder Root-Zertifikat, dem er vertrauen soll (ca: in Node.js, cafile= in Python, einen eigenen Pool für RootCAs in Go, --cacert in curl), oder installiere das Root-Zertifikat im Trust Store des Betriebssystems. Ein Zertifikat ohne DNS-Namen in der Erweiterung Subject Alternative Name scheitert auf andere Weise: Chrome gleicht den Common Name seit Version 58 (2017) nicht mehr ab, Apple-Plattformen seit iOS 13 und macOS 10.15.

Der Mittelweg: eine private CA

Eine private CA behält den größten Vorteil der Selbstsignierung (keine externe Partei, beliebige interne Namen, keine öffentliche Protokollierung) und beseitigt zugleich ihren größten Nachteil (das Vertrauen bei jeder Rotation neu verteilen zu müssen). Praktische Regeln:

  • Halte die Root-CA offline und stelle Zertifikate über eine Zwischen-CA aus; eine kompromittierte Zwischen-CA lässt sich ersetzen, ohne jeden Client anzufassen.
  • Beschränke die Namen auf deine internen Zonen, wie in der Demo, und halte pathlen und Key Usage eng.
  • Automatisiere die Leaf-Zertifikate: step-ca, Vault PKI und cert-manager können über ACME oder eigene APIs ausstellen, sodass Leaf-Zertifikate mit Laufzeiten von Stunden oder Tagen auskommen und ein Widerruf überflüssig wird.
  • Halte dich trotzdem an die Regeln der Clients: Apple-Plattformen verlangen für TLS-Zertifikate, die seit dem 1. Juli 2019 ausgestellt wurden, einen DNS-Namen im SAN, die Extended Key Usage serverAuth und eine Gültigkeit von höchstens 825 Tagen, auch bei privaten Root-CAs; die Grenze von 398 Tagen gilt nur für öffentlich vertrauenswürdige Root-CAs.
  • Plane die Verteilung des Root-Zertifikats: Trust Stores der Betriebssysteme, Java-Keystores, Container-Images, Browser mit eigenem Trust Store (Firefox) und Software mit eigenem Bundle (das Paket certifi hinter requests in Python sowie Node.js, das sein eingebautes Mozilla-Bundle verwendet, sofern es nicht mit --use-system-ca gestartet wird) – jedes davon braucht das Root-Zertifikat.

Wo eine öffentliche CA nicht weiterhilft

Öffentliche CAs dürfen keine Zertifikate mit internen Namen oder reservierten IP-Adressen ausstellen (Baseline Requirements §4.2.2). Namen wie printer.local, Hosts mit einteiligem Namen, 10.0.0.5 oder alles unter .internal – von ICANN am 29. Juli 2024 dauerhaft für die private Nutzung reserviert – können daher nur von einer privaten CA oder aus einem selbstsignierten Zertifikat stammen. Interne Hosts mit öffentlichen Namen (zum Beispiel db.corp.example.com) können über die DNS-01-Challenge öffentliche Zertifikate erhalten, ohne aus dem Internet erreichbar zu sein; dann erscheint aber jeder Name in den öffentlichen Logs von Certificate Transparency, und damit ist deine interne Topologie für jeden sichtbar, der diese Logs durchsucht.

Wann welche Variante passt

  • Öffentliche Websites, APIs und Mailserver: öffentliche CA mit ACME.
  • Interne Dienste, Service Meshes, mTLS zwischen Workloads: private CA mit kurzlebigen Leaf-Zertifikaten.
  • Lokale Entwicklung: eine lokale Entwicklungs-CA wie mkcert, die ihr Root-Zertifikat in deinen eigenen Trust Stores installiert, statt selbstsignierter Zertifikate, die jedes Tool auf andere Weise ablehnt.
  • Geräte und Appliances beim ersten Start: ein selbstsigniertes Zertifikat, dessen Fingerabdruck der Benutzer oder das Provisioning-System einmal prüft, danach die Registrierung bei einer privaten CA.
  • Test-Fixtures: selbstsignierte Zertifikate, die der Test selbst erzeugt und dem getesteten Client explizit übergibt.
  • Partner und B2B-Integrationen über mTLS: eine eigene private CA nur für diese Beziehung, nie deine allgemeine interne Root-CA.

Hinweise zur Migration

  1. Inventarisiere die verwendeten selbstsignierten Zertifikate: Scanne interne Endpunkte und sammle die Zertifikate, die Clients pinnen; der Zertifikats-Decoder zeigt Aussteller, SANs und Ablaufdatum.
  2. Richte eine private CA ein, mit einer Offline-Root-CA und einer ausstellenden Zwischen-CA, beschränkt auf deine internen Domains; erzeuge die CSRs mit dem CSR-Generator.
  3. Verteile das Root-Zertifikat, bevor du irgendeinen Server umstellst, und ersetze dann die Leaf-Zertifikate Dienst für Dienst; der Zertifikatsketten-Builder bestätigt, dass jeder Server sein Zwischenzertifikat mitsendet.
  4. Entferne unsichere Workarounds (-k, verify=False, InsecureSkipVerify), sobald die Clients dem Root-Zertifikat vertrauen, und durchsuche die Codebasis, damit sie nicht zurückkehren.
  5. Migriere öffentlich erreichbare Namen auf eine öffentliche CA mit ACME und setze das Pinning (falls überhaupt) auf Schlüssel statt auf Zertifikate; der SPKI-Pin-Generator berechnet Pins, die eine Erneuerung mit demselben Schlüssel überstehen.

Quellen

Alle Vergleiche