SSL Zertifikate

Dies ist eine kurze Anleitung zum Erstellen von SSL-Zertifikaten, insbesondere selbst-signierten Zertifikaten zum Betrieb von privaten Webservern.

Server key und sign-request erzeugen

Einen Server key und den dazugehörigen signing-request erstellt man so:

openssl genrsa -des3 -out server.key 4096 openssl req -new -key server.key -out server.csr

Die Angaben kann man beinahe nach Belieben eintragen, ausser bei common name (CN) muss zwingend der DNS Name des Servers eingetragen werden.

Passwort vom Server key entfernen

Um zu verhindern, dass der Webserver (Apache etc) beim starten jeweils nach dem Schlüsselpasswort fragt, muss dieses entfernt werden:

openssl rsa -in server.key -out server.key.nopass chown 0.0 server.key.nopass chmod 400 server.key.nopass

Achtung, wenn die Schlüsseldatei ohne Passwort entwendet wird, können Fremde sich als die jeweilige Website ausgeben (phishing)!

Serverkey für X509v3 erstellen

Dafür brauchen wir eine lokale config Datei:

csr.conf
[ req ] # default key size in bits. can be overridden by using the -newkey option. default_bits = 2048 # default filename to write private key to. default = stdout. can be overridden # by the -keyout option. default_keyfile = server.key # If this is set to no then if a private key is generated it is not encrypted. # This is equivalent to the -nodes command line option. For compatibility # encrypt_rsa_key is an equivalent option. encrypt_key = no # This option specifies the digest algorithm to use. default_md = sha256 # if set to the value no this disables prompting of certificate fields and just # takes values from the config file directly. It also changes the expected # format of the distinguished_name and attributes sections. prompt = no # if set to the value yes then field values to be interpreted as UTF8 strings, # by default they are interpreted as ASCII. This means that the field values, # whether prompted from a terminal or obtained from a configuration file, must # be valid UTF8 strings. utf8 = yes # This specifies the section containing the distinguished name fields to # prompt for when generating a certificate or certificate request. distinguished_name = my_req_distinguished_name # this specifies the configuration file section containing a list of extensions # to add to the certificate request. It can be overridden by the -reqexts # command line switch. See the x509v3_config(5) manual page for details of the # extension section format. req_extensions = my_extensions [ my_req_distinguished_name ] C = CH ST = Switzerland L = Winznau O = Mockmoon Cybernetics CN = your.servername.here [ my_extensions ] basicConstraints=CA:FALSE subjectAltName=@my_subject_alt_names subjectKeyIdentifier = hash [ my_subject_alt_names ] DNS.1 = your.servername.here

Diese wird dann so verwendet:

openssl req -new -out server.csr -config csr.conf

Variante 1: Selbstsignierten Schlüssel erzeugen (z.B. zum Testen)

Diese Variante ist sinnvoll, wenn man einen Serverkey nur kurzfristig zum Testen benötigt, oder eine SSL Verbindung ohne Überprüfung der Serveridendität benötigt wird.

Der Serverkey wird mit einer Gültigkeit von 1 Jahr selbst signiert:

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Variante 2: Schlüssel mit eigener CA signieren

Diese Variante macht vor allem Sinn, wenn in einem lokalen Netzwerk mehrere Server mit SSL Zertifikaten versehen werden sollen und/oder mehrere Clients langfristig auf diese(n) Server zugreifen sollen ohne ständig Warnmeldungen zu erhalten.
Es wird einmalig eine eigene Zertifizierungsstelle (CA) angelegt, deren (längerfristig gültiges) Zertifikat auf allen Clients installiert wird und mit deren Schlüssel dann alle Serverkeys signiert werden.

Einen eigenen, selbst signierten CA Schlüssel mit 10 Jahre gültigem Zertifikat erstellen (einmalig, bis Zertifikat abläuft):

openssl genrsa -des3 -out ca.key 4096 openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

Hinweis: Als CN darf hier kein Name angegeben werden, der mit einem späteren Servernamen (DNS) übereinstimmt. Am besten gibt man einen Leerstring ein.

Dann wird der Serverkey mit dem CA key signiert:

openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

Serverkey mit X509v3 Extensions mit dem CA key signieren

Dafür brauchen wir wieder eine lokale Konfiguration:

ca-sign.conf
# we use 'ca' as the default section because we're usign the ca command [ ca ] default_ca = my_ca [ my_ca ] # a text file containing the next serial number to use in hex. Mandatory. # This file must be present and contain a valid serial number. serial = ./serial # the text database file to use. Mandatory. This file must be present though # initially it will be empty. database = ./index.txt # specifies the directory where new certificates will be placed. Mandatory. new_certs_dir = ./newcerts # the file containing the CA certificate. Mandatory certificate = ./ca.crt # the file contaning the CA private key. Mandatory private_key = ./ca.key # the message digest algorithm. Remember to not use MD5 default_md = sha256 # for how many days will the signed certificate be valid default_days = 365 # a section with a set of variables corresponding to DN fields policy = my_policy [ my_policy ] # if the value is "match" then the field value must match the same field in the # CA certificate. If the value is "supplied" then it must be present. # Optional means it may be present. Any fields not mentioned are silently # deleted. countryName = match stateOrProvinceName = supplied organizationName = supplied commonName = supplied organizationalUnitName = optional commonName = supplied

Per Voreinstellung werden die Extensions aus dem CSR nicht übernommen. Dafür brauchen wir noch eine Konfig, separat für jeden CSR !

ext.conf
basicConstraints=CA:FALSE subjectAltName=@my_subject_alt_names subjectKeyIdentifier = hash [ my_subject_alt_names ] DNS.1 = your.servername.here

Evtl. müssen noch ein paar Dateien/Verzeichnisse initialisiert werden:

$ mkdir newcerts $ touch index.txt $ echo '01' > serial

Dann kann man den CSR mit dem CA key signieren:

$ openssl ca -config ca.conf -out server.crt -extfile ext.conf -in server.csr

Zertifikate installieren

Der Webserver benötigt jeweils sein Zertifikat (*.crt) und den zugehörigen Schlüssel (*.key).
Falls das CA Zertifikat auf die Clients verteilt werden soll, kann man es einfach irgendwo auf die Webseite installieren und dann per Browser den passenden URL aufrufen.

Besonderheiten bei lighttpd

lighttpd erwartet das Zertifikat und den dazugehörigen Schlüssel in einer Datei, und zwar erst den Schlüssel und dann das Zertifikat. Kein Problem:

cat server.key.nopass server.crt > /etc/lighttpd/server.pem

Sonstiges

Es lohnt sich, mal einen Blick auf letsencrypt.org zu werfen. Während ich diese Seite erstellt habe (Ende 2014) gab es dort zwar noch nichts funktionierendes, aber sehr vielversprechende Pläne!

Zu bearbeiten

cp ca.cert.pem /usr/share/ca-certificates/extra/ca.cert.crt
sudo update-ca-certificates
(maybe also see "man update-ca-trust" ?)
after this, CA should be known for tools like wget,curl,...

browsers dont look at system cert database, but instead have their own.

cert8.db ⇒ legacy dbm style cert database
cert9.db ⇒ current sqlite cert database

install libnss3-tools for certutil

certfile="root.cert.pem"
certname="My Root CA"
for certdb in $(find ~/ -name "cert9.db") do
	certdir=$(dirname ${certdb});
	certutil -A -n "${certname}" -t "TCu,Cu,Tu" -i ${certfile} -d sql:${certdir}
done