Eine CA mit Openssl

Für Anwendungen wie etwa OpenVPN, oder auch generell für Intranetanwendungen die SSL benutzen sollen, wird eine eigene CA (Certificate Authority) benötigt, die digitale Zertifikate ausstellt. Mit Openssl läßt sich solch eine CA betreiben.

Wozu eigentlich eine eigene interne CA, wenn Zertifikate auuch selbst signiert werden können? Ein selbstsigniertes Zertifikat wird von SSL-Clients als ungültig abgelehnt solange sie dieses Zertifikat nicht kennen. Wird das selbstsignierte Zertifikat im Client gespeichert, wird er es fortan akzeptieren. Betreibt man jedoch viele Serverdienste mit SSL und hat viele Clients, bedeutet es einen großen Aufwand jedem Client, jedes selbstsignierte Zertifikat bekannt zu geben. Mit einer CA werden die Zertifikate von der CA signiert. Kennt ein Client nun das Zertifikat der CA, wird er jedes Zertifikat welches von dieser CA signiert wurde als gültig akzeptieren. Die Clients müssen also nur noch ein CA Zertifikat zusätzlich lernen (welches außerdem eine längere Gültigkeitsdauer hat), als viele einzelne selbstsignierte Serverzertifikate.

Openssl ist nicht nur eine Bibliothek die Programmfunktionen für SSL bereit stellt, sondern enthält ebenso ein Kommandozeilenprogramm mit dem sich Schlüssel und Zertifikate erstellen lassen. Dieses Kommandozeilenprogramm hat sehr viele Optionen und es läßt sich gleichermassen nutzen um Serverzertifikate zu generieren, als auch um Passworthashes zu generieren und ebenso als vollständige CA.

Alle Openssl Kommandos werden mit openssl aufgerufen. Openssl hat Unterkommandos für seine vielen Funktionen. Das gewünschte Unterkommando wird beim Aufruf von openssl als erstes Argument übergeben, danach folgen die Optionen des jeweiligen Unterkommandos. Die Namen aller Unterkommandos lassen sich mit openssl list-standard-commands auflisten. Die folgende Tabelle zeigt eine Übersicht über einige der wichtigsten Unterkommandos.

Wichtige Unterkommandos von openssl
KommandoBedeutung
caVerwaltung einer CA.
dsaparamErzeugung einer DSA Parameter Datei.
genrsaErstellung eines RSA Schlüssels.
gendsaErstellung eines DSA Schlüssels.
reqVerwaltung von X.509 Certificate Signing Requests.
verifyVerifizierung von X.509 Zertifikaten.
x509X.509 Zertifikatsmanagement.

Die drei wichtigsten Unterkommandos zum Betrieb einer CA und zum erzeugen von Zertifikaten sind ca, welches alle Operationen für den Betrieb der CA zur Verfügung stellt, wie etwa das signieren von Certificate Signing Requests, req zum erzeugen eines Certificate Signing Requests, aber auch zum erzeugen selbstsignierter Zertifikate und x509 welches ein generelles Kommando zum Umgang mit Zertifikaten darstellt, welches Zertifikate konvertieren und anzeigen kann, aber auch in der Lage ist einfache CA Operationen wie etwa das Signieren selbst durchzuführen. Wie man am Kommando x509 sieht, überschneiden sich die Funktionen einiger Openssl Kommandos.

Openssl wird in fertigen Distributionspaketen häufig zusammen mit dem Script CA.pl ausgeliefert, welches ein Perlscript ist um eine CA zu verwalten. Das Script kapselt die eigentlichen openssl Kommandos und dient als Vereinfachung. Um Openssl richtig kennenzulernen ist es jedoch hilfreich die eigentlichen Kommandos kennen zu lernen, so daß hier nicht weiter auf dieses Script eingegangen wird. Möchte man ohnehin eine CA dauerhaft mit mehr Komfort betreiben, exitieren als Frontend zu Openssl mehrere grafische Programme, wie etwa TinyCA, ein Perlscript welches GTK+2 für die grafische Oberfläche nutzt und xca eine QT4 basierende Anwendung.

Da eine CA in einer PKI (Public Key Infrastructure) die Instanz ist, der alle anderen Rechner vertrauen, ist es wichtig eine CA bestmöglichst zu schützen. Keinesfalls sollte man eine CA direkt auf dem Rechner betreiben, der auch die Netzwerkdienste anbietet, für die die Zertifikate ausgestellt werden. In diesem Fall würde eine Kompromitierung dieses Servers auch automatisch eine Kompromitierung der gesamten CA bedeuten. Im Idealfall wird eine CA auf einem vom Netzwerk getrennten Einzelrechner betrieben, der in einem absperrbaren Zugangskontrollierten Raum steht. Ist eine CA einmal kompromitiert, kann der CA nicht mehr vertraut werden und alle ausgestellten Zertifikate sind wertlos.

Um nun eine CA anzulegen, benötigt die CA als erstes selbst ein Zertifikat. Da eine CA die Instanz ist die andere Zertifikate signiert, kann die CA ihr eigenes Zertifikat nur selbst signieren. Solch ein Zertifikat bezeichnet man als Root-Zertifikat. Zertifikate haben eine begrenzte Gültigkeitsdauer. Das Zertifikat einer CA muß in jedem Fall länger gültig sein, als die Zertifikate, die von ihr unterschrieben werden. Für ein CA Zertifikat wird daher eine relativ lange Gültigkeitsdauer gewählt, wie zum Beispiel 10 Jahre. Die Zertifikate die von der CA signiert werden, gelten meist nur für 1 - 2 Jahre.

Ein selbstsigniertes Root-Zertifikat für die CA wird mit openssl req angelegt. Vor dieser Aktion sollte jedoch die Openssl-Konfigurationsdatei angepaßt werden. Openssl hat eine Konfigurationsdatei, die im Aufbau einer Windows INI Datei ähnelt. Meist ist sie unter /etc/ssl/openssl.cnf zu finden. Diese Datei hat Bereiche, die jeweils durch einen Namen in eckigen Klammern abgegrenzt werden. Für die Unterkommandos req und ca kann es hier jeweils einen eigenen Bereich geben. Für den Betrieb einer CA muß außerdem auch noch ein Bereich [policy] benutzt werden, der festlegt welche Attribute in einem Zertifikat angegeben werden müssen und welche nicht. Da zunächst nur req eingesetzt wird, um das Root-Zertifikat der CA zu erstellen, wird in eine neue leere Konfigurationsdatei zunächst ein Bereich [req] definiert. Die von Openssl mitgelieferte Konfigurationsdatei sollte nicht gelöscht, sondern umbenannt werden um diese für Referenzzwecke aufzuheben. Die neue neue Konfigurationsdatei könnte so aussehen:

[req]
default_bits = 1024
distinguished_name = req_distinguished_name

Mit default_bits wird die Verschlüsselungsstärke eingestellt. Ohne diese Angabe verwendet Openssl einen 512 Bit RSA Schlüssel. Da 512 Bit für eine asymmetrische Verschlüsselung (welche größere Schlüsselstärken benötigt als symmetrische Verschlüsselung) nicht mehr besonders sicher ist, wird hier eine Verschlüsselungsstärke von 1024 Bit gesetzt. Sofern nicht anders angegeben wird RSA Verschlüsselung verwendet. Diese Angabe läßt sich auf der Kommandozeile mit der Option -newkey überschreiben. Soll zum Beispiel ein 768 Bit RSA Schlüssel verwendet werden müßte -newkey rsa:768 angegeben werden. Möchte man stattdessen DSA Verschlüsselung, muß zuvor eine DSA Parameter Datei erstellt werden. Die Verschlüsselungsstärke wird dabei beim generieren der DSA Parameterdatei angegeben. Folgendes Kommando erstellt eine DSA Parameter Datei mit einer Stärke von 1024 Bit:

openssl dsaparam -out dsaparam 1024

Der Dateiname der Datei ist in diesem Beispiel einfach dsaparam. Um anschließend die Datei beim erzeugen eines Schlüssels zu verwenden muß der Wert für die Option -newkey so aussehen: -newkey dsa:dsaparam.

Mit distinguished_name wird der Name eines zusätzlichen Bereiches in der Konfigurationsdatei angegeben, in welchem die Fragen die beim erzeugen eines Zertifikats gestellt werden, konfiguriert werden. Diese Angabe ist notwendig um die zusätzlichen Attribute die ein SSL-Zertifikat benötigt angeben zu können. Diese zusätzlichen Attribute sind standardisiert. Folgende Attribute existieren:

countryName
Name des Landes als 2-buchstabiges Kürzel (zum Beispiel DE für Deutschland
stateOrProvinceName
Name des Staates, bzw. Bundeslandes
localityName
Name der Stadt
organizationName
Name der Organisation oder Firma
organizationalUnitName
Name der Abteilung in der Organsiation oder Firma
commonName
Dies ist im allgemeinen der Hostname des Servers für den das Zertifikat ausgestellt wird. Dabei ist wichtig, das dieser Name übereinstimmt mit dem Namen über den der Dienst später aufgerufen wird.

Diese Namen existieren als Felder in jedem Zertifikat, was jedoch nicht heißt, das diese Felder auch alle Pflichtfelder sein müssen. Es können durchaus einzelne Felder (wie etwa organizationalUnitName) leer bleiben. Darüber hinaus existieren noch ein paar weitere Felder die zusätzlich eingefügt werden können, wie vor allem emailAdress, welches die Emailadresse des Inhabers enthält. In der Konfigurationsdatei müssen für diese Attribute Fragen angegeben werden, welche bei einem openssl req Kommando gestellt werden. Die Antworten werden in die entsprechenden Felder des Zertifikats eingetragen. Der Bereich [req_distinguished_name] könnte zum Beispiel so aussehen:

[req_distinguished_name]
countryName = Name des Landes als 2-Buchstabencode?
countryName_default = DE
countryName_min = 2
countryName_max = 2
stateOrProvinceName = Bundesland?
localityName = Stadt?
organizationName = Organisationsname (zum Beispiel Firmenname)?
organizationalUnitName = Abteilung?
commonName = Common Name (meist der Hostname)?
emailAddress = Email Adresse?

Zusätzlich zu den Fragen läßt sich für jedes Attribut auch ein Standardwert angeben, der benutzt wird, wenn eine Frage nicht beantwortet wurde. Dieser Standardwert wird mit attributName_default angegeben. In diesem Beispiel wird dies für das Land mit countryName_default = DE benutzt. Ebenso kann auch eine maximale Länge und eine minimale Länge für ein Attribut mit attributName_min und attributName_max angegeben werden.

Wurde die Konfigurationsdatei angelegt, kann nun ein selbstsigniertes Zertifikat für die CA erstellt werden:

openssl req -x509 -new -days 3650 -keyout privkey.pem -out pubkey.pem

Dieses Kommando verlangt zunächst eine Passphrase mit welcher der neue private Schlüssel verschlüsselt wird und fragt dann die vorher konfigurierten Fragen um die benötigten Attribute in das Zertifikat aufzunehmen. Dabei sollte allerdings für commonName nicht der Hostname des CA Rechners angegeben werden, sondern eher etwas wie "CA". Anschließend werden die beiden Dateien pubkey.pem und privkey.pem erstellt, wobei privkey.pem der neue private Schlüssel ist und pubkey.pem das neue selbstsignierte Zertifikat ist. Die Option -x509 sorgt dafür das ein selbstsigniertes Zertifikat, statt eines Certificate Signing Requests erzeugt wird. Mit der Option -new wird verlangt das ein neues Schlüsselpaar angelegt wird und die Option -days gibt die Gültigkeitsdauer des Zertifikats in Tagen an. Hätte man ein unverschlüsseltes Zertifikat ohne Passphrase erstellen wollen, müßte die Option -nodes angegeben werden. Dies sollte jedoch für ein CA Root-Zertifikat keinesfalls gemacht werden sollte, da die Passphrase das Zertifikat zusätzlich vor Missbrauch schützt. Die folgende Tabelle führt einige der wichtigsten Optionen von openssl req auf:

Wichtige Optionen von openssl req
OptionBedeutung
-x509Erzeugt ein selbstsigniertes Zertifikat statt eines Certificate Signing Requests
-newErzeugt einen neuen Certificate Signing Request (oder ein neues Zertifikat falls mit -x509 verwendet).
-nodesErzeugt einen privaten Schlüssel der nicht zusätzlich mit einer Passphrase verschlüsselt ist.
-daysGibt die Gültigkeitsdauer des Zertifikats in Tagen an.
-keyoutDatei in die der neue private Schlüssel geschrieben werden soll.
-outDatei in die der Certificate Signing Request oder das neue Zertifikat geschrieben wird.
-newkeyVerschlüsselungsalgorithmus der verwendet werden soll. Zum Beispiel rsa:1024 für einen 1024 Bit RSA Schlüssel, oder dsa:dsaparam für einen DSA Schlüssel der die vorher erzeugte DSA-Parameter Datei dsaparam benutzt.
-configNormalerweise wird die Standardkonfigurationsdatei (meist /etc/ssl/openssl.cnf) benutzt. Hiermit wird eine alternative Datei als Konfigurationsdatei angegeben.
-inDatei aus der ein Certificate Signing Request gelesen wird. Darf nicht mit -new kombiniert werden.
-keyDatei aus der ein privater Schlüssel gelesen wird.

Möchte man sein frisch erstelltes CA Zertifikat mit allen enthaltenen Informationen betrachten, kann folgender Befehl verwendet werden:

openssl x509 -text -in pubkey.pem

Die Option -text des x509 Kommandos dient dazu alle in einem Zertifikat enthaltenen Informationen als Klartext auszugeben. Mit der Option -in wird das entsprechende Zertifikat angegeben.

Um eine CA zu betreiben muß die Konfigurationsdatei noch etwas erweitert werden. In der Konfigurationsdatei können dabei mehrere Bereiche mit jeweils unterschiedlichen Konfigurationen für eine CA erstellt werden, so das es unterschiedliche Profile innerhalb einer CA geben kann zum Beispiel für unterschiedliche Arten von Zertifikaten (Serverzertifikate, Clientzertifikate, etc.). Ein Bereich gilt dabei als Default CA und wird im [ca] Bereich der Konfigurationsdatei angegeben. Der [ca]-Bereich könnte daher so aussehen:

[ca]
default_ca = Myca

In diesem Beispiel muß es einen Bereich Namens [Myca] geben, in der die Konfiguration für die Default CA steht:

[Myca]
dir = ./myca
database = $dir/index.txt
new_certs_dir = $dir/newcerts
certificate = $dir/cacert.pem
serial = $dir/serial
private_key = $dir/private/cakey.pem
default_md = sha1
default_days = 365
policy = mypolicy

Diese Konfiguration legt das Unterverzeichnis myca als Ort für die CA-Dateien fest. Mit database wird eine Textdatei definiert, in der alle neuen Zertifikate eingetragen werden. Mit new_certs_dir wird ein Verzeichnis festgelegt in welches neu signierte Zertifikate kopiert werden. certificate verweist auf das CA-Zertifikat und private_key auf den privaten Schlüssel der CA. Mit serial wird eine Textdatei angegeben die die nächste Seriennummer für die signierten Zertifikate enthält. default_md bestimmt den verwendeten Hashalgorithmus (MD5 oder SHA1). Mit default_days wird die Gültigkeitsdauer des neuen Zertifikates angegeben. Mit policy wird ein zusätzlicher Bereich angegeben der die Policy für durch die CA zu signierende Zertifikate enthält. Dieser Bereich könnte zum Beispiel so aussehen:

[mypolicy]
countryName = supplied
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied

Für einen Policy-Bereich muß zu jedem Attribut angegeben werden ob dieses mit dem entsprechenden Attribut des CA Zertifikates übereinstimmen muß (match), oder ob das Attribut zwar nicht übereinstimmen muß, aber vorhanden sein muß (supplied), oder ob das Attribut optional ist (optional). In diesem Beispiel müssen keine Attribute übereinstimmen, countryName und commonName müssen vorhanden sein, während alle anderen Angaben optional sind.

Anschließend muß noch die in der Konfigurationsdatei angegebene Verzeichnishierarchie angelegt werden. Mit den hier gezeigten Beispielen muß dazu das Unterverzeichnis myca angelegt werden, welches die beiden Unterverzeichnisse private und newcerts enthalten muß. Außerdem muß die Datei index.txt als neue leere Datei in diesem Verzeichnis angelegt werden. Ebenso muß auch die Datei für die Seriennummer angelegt werden. In diese Datei wird ein Startwert für die Serienummer geschrieben, zum Beispiel 01:

mkdir -p myca/private
mkdir myca/newcerts
touch myca/index.txt
echo "01" > myca/serial

Danach muß noch das vorher erzeugte Zertifikat (pubkey.pem) nach myca/cacert.pem und der private Schlüssel (privkey.pem) nach myca/private/cakey.pem kopiert werden. Um den privaten Schlüssel möglichst gut zu schützen werden auch noch die Rechte auf das Verzeichnis private angepaßt:

mv pubkey.pem myca/cacert.pem
mv privkey.pem myca/private/cakey.pem
chmod 700 myca/private

Anschließend ist die CA bereit um Zertifikate zu signieren. Um nun etwas zu signieren wird ein Certificate Signing Request für ein Testzertifikat erstellt:

openssl req -new -nodes -days 730 -keyout testkey.pem -out testreq.req

Dies erzeugt die beiden Dateien testkey.pem als neuen privaten Schlüssel und testreq.req als Certificate Signing Request. Durch die Angabe der Option -nodes wird der private Schlüssel nicht mit einer Passphrase verschlüsselt. Für Serverzertifikate ist dies meist erwünscht, da sonst bei jedem Start des Serverdienstes die Passphrase mit angegeben werden müßte. Durch -days 730 soll das Zertifikat eine Gültigkeitsdauer von 2 Jahren haben. Dieser Wert kann aber beim signieren durch die CA einfach überschrieben werden.

Um den Certificate Signing Request nun durch die CA zu signieren, ist folgender Befehl aus dem Verzeichnis oberhalb von myca notwendig:

openssl ca -in testreq.req -out testcert.pem

Dabei wird nach der Passphrase des privaten CA Schlüssels gefragt. Anschließend werden die Attribute welche im Certificate Signing Request enthalten sind angezeigt und man wird gefragt ob dieses Zertifikat wirklich signiert werden soll. Beantwortet man die Frage mit y für yes, wird das Zertifikat in der neuen Datei testcert.pem erstellt. Der Certificate Signing Request in testreq.req kann anschließend gelöscht werden. Auf dem Server der das SSL Zertifikat nutzen soll, muß das neue Zertifikat zusammen mit dem privaten Schlüssel, der vorher erzeugt wurde, hinterlegt werden.

Beim signieren von Zertifikaten wird automatisch die Seriennummer in der Datei myca/serial hochgezählt und jedes neue Zertifikat wird in die Datei myca/index.txt eingetragen. Außerdem wird eine Kopie des Zertifikates in das Verzeichnis myca/newcerts abgelegt. Die Kopie trägt den Dateinamen der Seriennummer plus der Erweiterung .pem.

Die folgende Tabelle listet wichtige Kommandozeilenoptionen des openssl ca Befehls auf:

Optionen von openssl ca
OptionBedeutung
-configWählt eine alternative Konfigurationsdatei aus.
-inGibt die Datei mit dem Certificate Signing Request an, die signiert werden soll.
-outDatei in der das neue signierte Zertifikat gespeichert wird.
-certGibt die Datei mit dem CA Zertifikat an.
-keyfileGibt den privaten Schlüssel der CA an.
-daysGibt die Gültigkeitsdauer des Zertifikats in Tagen an.
-mdGibt den verwendeten Hashalgorithmus an. Mögliche Werte md5 oder sha1.
-nameGibt den Namen des Bereichs in der Konfigurationsdatei an, der als Konfiguration verwendet werden soll. Möchte man einen anderen Bereich als den der default_ca benutzen muß diese Option verwendet werden.
-policyGibt den Policy-Bereich in der Konfigurationsdatei an, der verwendet werden soll.

René Maroufi, dozent (at) maruweb.de
Creative Commons By ND