Let's Encrypt Zertifikate mit HTTP Public Key Pinning (HPKP) und DANE

In mindestens zwei Anwendungsfällen ist die geringe Laufzeit von Let’s Encrypt Zertifikaten lästig: Bei der Nutzung von HPKP (Public Key Pinning) und DANE. Beide Verfahren sollen HTTPS-Verbindungen zusätzlich absichern, indem genau spezifiziert wird, welche TLS-Zertifikate für eine Domain gültig sein sollen. Da mindestens alle 90 Tage ein anderes Let’s Encrypt -Zertifikat eingerichtet werden muss, müssen in diesem Zyklus auch die HPKP- und DANE-Einstellungen mehr oder weniger aufwendig aktualisiert werden.

Der Aufwand lässt sich jedoch mit einem Trick reduzieren: Da beide Verfahren auf der Untersuchung des Public Keys im öffentlichen Zertifikat beruhen, kann man dafür sorgen, dass sich dieser bei der Umstellung auf ein neues Zertifikat nichts ändert. Man verwendet daher bei der Beantragung eines neuen LE-Zertifikats also keinen neuen Private Key, sondern einen alten. (Der Public Key basiert auf dem Private Key). Um einen alten Key nutzen zu können, muss der Referenzclient von Let’s Encrypt im Zusammenspiel mit einem eigenen, gleich bleibenden Private Key und einer eigenen Zertifikatsanfrage (CSR) verwendet werden.

Zuerst wird ein neuer, privater Schlüssel erstellt:

openssl genrsa -out privkey.pem 4096

Für eine komfortablere Generierung der Zertifikatsanfrage wird eine Konfigurationsdatei “request.cnf” mit diesem Inhalt erstellt:

[ req ]
default_md = sha512
prompt = no
encrypt_key = no
distinguished_name = req_distinguished_name
req_extensions = v3_req

[ req_distinguished_name ]
countryName = "DE"
stateOrProvinceName = "Bayern"
localityName = "Landshut"
postalCode = "1234"
streetAddress = "LE Strasse 42"
organizationName = "trashserver.net"
organizationalUnitName = "IT"
commonName = "trashserver.net"
emailAddress = "admin@domain.tld"

[ v3_req ]
subjectAltName = DNS:www.trashserver.net,DNS:xmpp.trashserver.net

Was unter “req_distinguished_name” steht, hat für Let’s Encrypt Zertifikate keine Bedeutung, da diese Daten nicht in das Zertifikat aufgenommen werden. Ihr könnt hier Phantasienamen oder auch nichts eingeben ;) Wichtig ist hier nur der “commonName”: Das ist die Hauptdomain, für die das Zertifikat gelten soll. Alle weiteren Domains werden ganz unten nacheinander angegeben.

Nun wird mithilfe des Private Keys “privkey.pem” und der Konfigurationsdatei eine Zertifikatsanfrage gestellt:

openssl req -config request.cnf -new -key privkey.pem -out request.csr -outform der

Im aktuellen Verzeichnis sollte sich nun eine Datei “request.csr” befinden.

Ihr könnt die CSR jetzt verwenden, um bei Let’s Encrypt neue Zertifikate zu beantragen:

./letsencrypt-auto certonly -a manual --key-path privkey.pem --cert-path cert.pem --fullchain-path fullchain.pem --csr request.csr

Folgt dabei der üblichen Bestätigungsprozedur, die in diesem Artikel bereits erklärt wurde.

Danach findet ihr in eurem Verzeichnis ein paar neue Dateien:

  • 0000_cert.pem: Euer neues Zertifikat
  • 0000_fullchain.pem: Euer neues Zertifikat + Chain

Zertifikat erneuern

Sollte dieses neu generierte Zertifikat einmal ablaufen, braucht ihr dem Let’s Encrypt Client nur wieder die request.csr Datei übergeben und erhaltet ein neues Zertifikat. Falls ihr neue Domains in euer Zertifikat aufnehmen wollt, muss die request.cnf zuvor entsprechend erweitert und eine neue Zertifikatsanfrage “request.csr” generiert werden.

Einsatz mit DANE

Im Zusammenspiel mit DANE spart man sich den Umstellungsaufwand nur, wenn dieses so konfiguriert ist, dass nicht auf dem ganzen Zertifikat der Hash berechnet wird, sondern nur auf den Public Key-Daten. Dafür wird der mittlere Zahlenparameter im TLSA-Record auf eine 1 statt einer 0 gesetzt, z.B. so:

_990._tcp.example.com IN TLSA 2 1 2 2CFC98A706BCF3683015...

Mehr zum Thema DANE und TLSA Records könnt ihr in diesem Beitrag nachlesen: DANE und TLSA Records erklärt

Noch ein Wort zur Sicherheit

Eigentlich sollte man für jedes neue Zertifikat einen neuen Private Key verwenden und den alten nicht mehr nutzen - das hat gute Gründe: Sollte der private Schlüssel von einer fremden Partei evtl. doch einmal in Erfahrung gebracht werden, kann der Datenverkehr nur für maximal 90 Tage mitgelesen werden. Nutzt man den privaten Schlüssel länger, sind auch neue Zertifikate nicht mehr sicher. Ich bin allerdings der Meinung, dass es vertretbar ist, denselben Schlüssel ein Jahr lang (= 3 Wiederverwendungen) zu nutzen, da kommerzielle Zertifikate auch mindestens ein Jahr lang mit demselben Private Key gültig sind. Nach einem Jahr sollte man allerdings ein neues Zertifikat mit einem neuen Private Key erzeugen.