Perfect Forward Secrecy, eine Zusammenfassung

Abstract

Perfect Forward Secrecy ist Bestandteil des Key Agreement Protocol. Simpel formuliert geht es darum, dass der während einer Sitzung ausgehandelte Key (Session Key) auch in Zukunft nicht kompromittiert werden kann, selbst wenn ein beteiligter privater Schlüssel kompromittiert worden ist. Dieses Verfahren basiert auf Diffie-Hellman Algorithmen,...

Until Recently, cryptography has been of interest primarily to the military and dipomatic communities. Private individuals and even commercial organizations have rarely considered it necessary to resort to encryption for the protection of their communications, and those that have, have seldom done so with particular care.

--Whitfield Diffie & Martin E. Hellman (März 1979)

Dieses Zitat entstammt dem Papier Privacy and Authentication: An Introduction to Cryptography. Mir scheint, daran hat sich in den letzten 35 Jahren nichts geändert, aber das soll nun alles anders werden. In ihrem Papier New Directions in Cryptography (November 1976) beschreiben die Autoren ein Public Key System sowie das Modell eines one-way authentication systems, heute allgemein bekannt als Diffie-Hellman-Algorithmus. Dieses Modell wurde als RFC-2631 veröffentlicht. An dieser Stelle möchte ich nicht ausführlich darauf eingehen, Wikipedia hat dies ausführlicher und verständlicher dargestellt, als ich es je könnte.

Perfect Forward Secrecy ist Bestandteil des Key Agreement Protocol. Simpel formuliert geht es darum, dass der während einer Sitzung ausgehandelte Key (Session Key) auch in Zukunft nicht kompromittiert werden kann, selbst wenn ein beteiligter privater Schlüssel kompromittiert worden ist. Dieses Verfahren basiert auf Diffie-Hellman-Algorithmen, diese werden in zwei unterschiedlichen Modi eingesetzt:

  • Diffie-Hellman Ephemeral (DHE)
  • Diffie-Hellman Eliptic Curves (DHEC)

Diese kryptographischen Methoden werden u.a. auch im Bereich des sicheren Datentransports mittels Tranport Layer Security eingesetzt. Die aktuelle Version beschreibt TLS Protocol Version 1.2 . Dieser Einsatz soll im folgenden beschrieben werden.

APIs und Development Kits

Es gibt mehrere APIs und Development Kits, die die Verwendung von TLS ermöglichen. Eine umfassende Sammlung von Implementierungen bietet Wikipedia. Nicht alle sind in der Lage, DHE und DHEC zu realisieren. In der Open-Source-Welt sind

  • Mozilla NSS
  • OpenSSL
  • GnuTLS

am weitesten verbreitet. MOZNSS hat meines Wissens weder DHE noch DHEC für Server implementiert, allerdings sind TLS-Clients, die mit MOZNSS komiliert wurden, in der Lage, DHE Session Keys zu generieren. GnuTLS hat DHE rudimentär implementiert. OpenSSL bietet APIs sowohl für DHE als auch DHEC an.

Caution!

Debian hat die Funktion Diffie Hellman Eliptic Curve in OpenSSL deaktiviert.

Anwendungen, die unter Debian mit libssl, libcrypto und ecdh.h kompiliert wurden, können keine Zertifikate interpretieren, die mit openssl ecparam erstellt wurden.

PFS mit OpenSSL DHE

Sofern die gegebenen Netzwerk-Services schon mit TLS oder STARTTLS operieren, ist die zusätzliche Implementierung von PFS recht einfach und schnell zu realisieren. Es gilt allerdings zu beachten, dass der Client bei STARTTLS zuerst eine unverschlüsselte Verbindung herstellt und erst nach Schlüsselaustausch und -validierung eine Transportverschlüsselung hergestellt wird, daher ist PFS mit STARTTLS nicht zu empfehlen, obwohl es prinzipiell realisierbar ist. DHE, also mit Ephemeral Keys , ist nur dann sinnvoll, wenn nur der Server ein Hostzertifikat präsentiert und der Client dieses mit der CA verifiziert. Wenn sowohl Client als auch Server sich jeweils mit einem eigenen Zertifikat authentisieren, ist eine static-static Situation gegeben, in der der generierte ephemeral Key immer identisch sein wird.

Im Blog X.509 Certificates wird beschrieben, wie X.509 Certificates mittels OpenSSL erstellt werden. An dieser Stelle soll daher nur beschrieben werden, wie Certificates mittels openssl dhparam ergänzt und wie sie eingesetzt werden können. In älteren OpenSSL-Versionen wurden noch die Tools dh und gendh dokumentiert, diese sind aber obsolet.

$ openssl dhparam -help
   dhparam [options] [numbits]

  gibt folgende Optionen:

-inform arg   input format one of DER PEM
-outform arg  output format one of DER PEM
-in arg       input file
-out arg      output file
-dsaparam     read or generate DSA parameters convert to DH
-check        check the DH parameters
-text         print a text form of the DH parameters
-C            Output C code
-2            generate parameters using  2 as the generator value
-5            generate parameters using  5 as the generator value
-engine e     use engine e possibly a hardware device.
-rand         "file:file"
-load         the file (or the files in the directory)
             into the random genrator
-noout        no output
numbits       number of bits in to generate (default 512)

Die wichtigsten Optionen sind -2 und -5 zur Bezeichnung eines Generators, dazu ist anzumerken, dass es auch in früheren Versionen einen Generator -3 gab, der aber im Quellcode deaktiviert wurde. Weiterhin ist die Anzahl der Bits wichtig, der Default von 512 ist heutzutage zu niedrig, es werden allgemein 2048 empfohlen. Dazu noch der Hinweis, dass Java einschließlich der Version 1.7, nur 1024 Bit beherrscht.

Nun zur Erzeugung eines Zertifikates:

$ openssl dhparam -2 -out dh-2048.pem 2048

Das Zertifikat kann man sich jetzt auch noch ansehen:

$ openssl dhparam -in dh-2048.pem -noout -text

  PKCS#3 DH Parameters: (2048 bit)
      prime:
          00:b6:1a:8a:ce:5f:08:a0:91:be:19:ee:20:12:9a:
          4e:44:c9:05:f0:5c:ba:45:19:83:3e:39:1a:c7:3a:
          5d:bb:4c:88:84:2b:d4:e8:1d:7e:02:33:e1:ae:28:
          13:0b:9b:0d:05:c3:13:63:b5:a4:db:45:30:8d:06:
          2c:c4:9e:3d:b7:1d:df:9f:36:37:cf:ad:7c:3f:4e:
          a9:3b:e9:92:d0:80:46:c5:2a:73:bd:49:56:17:3d:
          ca:9f:24:3f:d3:22:4e:f0:2a:52:2e:35:a3:59:03:
          13:66:08:cf:b0:94:46:5d:dd:82:71:d0:b7:fb:fb:
          37:5c:f7:7f:c5:e4:df:ba:55:88:df:8e:0b:95:19:
          6a:da:31:92:bc:96:9d:38:2f:1e:cb:41:54:b5:95:
          b7:c8:cc:f4:42:9c:6d:e3:bd:26:31:5b:65:78:3c:
          3f:6f:d4:93:a1:26:7d:6a:ba:ac:c6:94:72:24:1e:
          4e:d0:6c:2e:8e:4a:ad:20:c7:8f:2b:f5:b7:71:d9:
          1b:a2:39:60:73:45:18:56:db:ee:63:a6:bd:b8:c5:
          04:ab:0d:3c:f5:8f:44:ad:b2:97:d6:8e:aa:2f:d2:
          cc:b3:f5:6e:6b:7c:2f:be:5e:81:f2:91:5b:e9:d5:
          4a:12:47:24:58:ef:4f:4d:48:c1:72:45:2f:51:96:
          56:b3
      generator: 2 (0x2)

Nun kann eine Anwendung, zusätzlich zum CA-Zertifikat und zum Host-Zertifikat, mit diesem DHE-Zertifikat konfiguriert werden, der entsprechende Parameter ist TLS_DHPARAM_FILE, je nach Anwendung mag es nicht versal geschrieben sein, oder auch ohne Unterstrich. Grundsätzlich gilt aber für alle mit OpenSSL kompilierten Anwendungen der gleiche Konfigurationsparameter.

Am Beispiel von OpenLDAP soll nun die Wirkweise demonstriert werden. Zuerst die entsprechende Konfiguration in slapd.conf,

TLSCACertificateFile    /etc/openldap/certs/myCA.pem
TLSCertificateFile      /etc/openldap/certs/host.pem
TLSCertificateKeyFile   /etc/openldap/certs/host-key.pem
TLSVerifyClient         try
TLSCipherSuite          HIGH:TLSv1.2:SSLv3:!SSLv2
# TLSCipherSuite         aRSA+AES128+kEDH
TLSDHParamFile          /etc/openldap/certs/dh-2048.pem
# TLSDHParamFile        /dev/null

Hier zeige ich noch eine Alternative auf, nämlich /dev/null als Wert für TLSDHParamFile; dies ist eine gültige Option, die Datei dh.include weist ausdrücklich darauf hin – es wird dann ein intern generierter Wert benutzt.

Zum Schluss soll noch geprüft werden, ob slapd nun PFS ermöglicht:

$ openssl s_client -connect localhost:636 -debug -state

Die darauf folgende Datenmenge möchte ich nicht dokumentieren, wichtig ist der folgende Auszug:

SSL_connect:SSLv3 read server certificate A
read from 0x19d0990 [0x19d6923] (5 bytes => 5 (0x5))
0000 - 16 03 03 02 0f                                    .....
read from 0x19d0990 [0x19d6928] (527 bytes => 527 (0x20F))
0000 - 0c 00 02 0b 01 00 ad bd-87 a6 48 48 1e 7d 43 f3

Mit dem Wert 0c beginnt das ausgehandelte ephemerale Zertifikat, 00 02 0b bestimmen die Länge des Zertifikats, 01 00 zeigen an, dass es sich um 2048 Bit handelt, 00 80 würde auf 1024 Bit deuten. Dies alles viele Zeilen später in etwas lesbarer Form:

SSL handshake has read 3173 bytes and written 531 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: zlib compression
Expansion: zlib compression
SSL-Session:
 Protocol  : TLSv1.2
 Cipher    : DHE-RSA-AES256-GCM-SHA384

Quod erat demonstrandum!

PFS mit OpenSSL DHEC

Die Berechnung von Diffie-Hellman-Algorithmen kann sehr aufwändig und langwierig sein. Um diese Rechenleistung zu reduzieren, werden Punkte elliptischer Kurven herangezogen. Das "National Institute of Standards and Technologie" (NIST) hat etliche Standardkurven berechnen lassen, diese sind auch in OpenSSL eingebunden.

$ openssl ecparam -list_curves
 secp112r1 : SECG/WTLS curve over a 112 bit prime field
 secp112r2 : SECG curve over a 112 bit prime field
 secp128r1 : SECG curve over a 128 bit prime field
 secp128r2 : SECG curve over a 128 bit prime field
 secp160k1 : SECG curve over a 160 bit prime field
 secp160r1 : SECG curve over a 160 bit prime field
 secp160r2 : SECG/WTLS curve over a 160 bit prime field
 secp192k1 : SECG curve over a 192 bit prime field
 secp224k1 : SECG curve over a 224 bit prime field
 secp224r1 : NIST/SECG curve over a 224 bit prime field
 secp256k1 : SECG curve over a 256 bit prime field
 secp384r1 : NIST/SECG curve over a 384 bit prime field
 secp521r1 : NIST/SECG curve over a 521 bit prime field
 ...

Diese Liste ist noch entschieden länger, das Thema sollte auch nur kurz angerissen werden. Nicht alle Standardkurven können mit allen Anwendungen genutzt werden. Hier hilft nur die Erfahrung.

Note

Elliptische Standardkurven des NIST sind nicht unumstritten, ein jeder mag seine eigene Situation beurteilen.

Im Gegensatz zur oben beschriebenen Methode einer zusätzlichen Berechnungsbasis als Datei, werden bei der Methode DHEC die Werte der Kurvenberechnungen in das Zertifikat integriert. Zur Erstellung eines Zertifikats stehen die folgenden Optionen zur Verfügung:

$ openssl ecparam -help

  ecparam [options] <infile >outfile
 where options are
 -inform arg       input format - default PEM (DER or PEM)
 -outform arg      output format - default PEM
 -in  arg          input file  - default stdin
 -out arg          output file - default stdout
 -noout            do not print the ec parameter
 -text             print the ec parameters in text form
 -check            validate the ec parameters
 -C                print a 'C' function creating the parameters
 -name arg         use the ec parameters with 'short name' name
 -list_curves      prints a list of all currently available curve 'short names'
 -conv_form arg    specifies the point conversion form
                  possible values: compressed
                                   uncompressed (default)
                                   hybrid
 -param_enc arg    specifies the way the ec parameters are encoded
                  in the asn1 der encoding
                  possible values: named_curve (default)
                                   explicit
 -no_seed          if 'explicit' parameters are choosen do not use the seed
 -genkey           generate ec key
 -rand file        files to use for random number input
 -engine e         use engine e, possibly a hardware device

1. Erstellen eines privaten CA Key

$ openssl ecparam -name secp384r1 -out ca-key.pem -genkey

2. Erstellen einer CA

$ openssl req -new -x509 -key ca-key.pem -out ca-cert.pem

Hier müssen natürlich noch die entsprechenden Optionen, wie im Blog zu X.509 beschrieben, hinzugefügt werden.

3. Erstellen eines private Host-Key

$ openssl ecparam -name secp384r1 -out host-key.pem

4. Erstellen eines Host-Certificate Signing Requests

$ openssl req -new -key host-key.pem -out host-cert.csr

Auch hier können noch zusätzliche Parameter hinzugefügt werden.

5. Erstellen eines Host Zertifikates

$ openssl ca -config host.cnf -infiles host-cert.csr -out host-cert.pem

Dies ist nur eine rudimentäre Beschreibung. Diese Zertifikate kann ich noch nicht testen, da die libldap erst in der Version 2.5 DHEC unterstützen wird. Das hängt damit zusammen, dass eine Änderung der API erfolgen muss – dies ist aber mit einer neuen Release-Nummer verbunden. Wer mag, kann natürlich schon den aktuellen Quellcode aus dem git Repository holen.

Dieter Klünter, 09. September 2013