OpenSSL ist ein Werkzeugkasten für kryptografische Funktionen. Er ermöglicht den Betrieb einer PKI mit eigener Zertifizierungsstelle. Wir erzeugen hier Schlüssel und Zertifikate für unsere Server. Im Idealfall liegen die Daten auf einem sicheren Rechner ohne Verbindung zum Internet, aber ein verschlüsselter Arbeitsplatzrechner tut es auch.
Das Paket openssl
enthält das gleichnamige Programm
und die zugehörige Dokumentation.
apt install openssl
Standardmäßig liest das Programm openssl
Voreinstellungen aus der globalen Konfigurationsdatei
/etc/ssl/openssl.cnf
. Wir legen für jede
Zertifizierungsstelle eine eigene Datei an.
Die ersten Abschnitte konfigurieren das Ausstellen
von Zertifikaten beim Aufruf des Subkommandos ca
.
Wir speichern alle Dateien im Arbeitsverzeichnis.
openssl.cnf[ca] default_ca = illusioni_ca [illusioni_ca] dir = . # Where everything is kept certs = $dir # - issued certificates crl_dir = $dir # - issued crl's new_certs_dir = $dir # - new certificates RANDFILE = $dir/.rand # Private random number file serial = $dir/serial # Certificate serial number crlnumber = $dir/crlnumber # Revocation serial number database = $dir/index.txt # Database of issued certificates certificate = $dir/ca.crt # CA certificate private_key = $dir/ca.key # CA private key crl = $dir/crl.pem # Revocation List x509_extensions = usr_cert # Extensions for issued certificates name_opt = ca_default # Subject Name options cert_opt = ca_default # Certificate field options default_days = 365 # How long to certify for default_crl_days = 30 # How long before next CRL default_md = default # Public key default preserve = no # Keep passed DN ordering policy = illusioni_policy # Similarity constraints [illusioni_policy] countryName = match stateOrProvinceName = optional organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional
Die nächsten Abschnitte konfigurieren das Anfordern von Zertifikaten und welche Felder abgefragt werden.
# Key Generation and Certificate Signing Request [req] default_bits = 2048 default_keyfile = private.key string_mask = utf8only distinguished_name = req_dn attributes = req_attr x509_extensions = v3_ca # Extensions for self signed certificate req_extensions = v3_req # Extensions for certificate requests [req_dn] countryName = Country Name (2 letter code) countryName_default = DE countryName_min = 2 countryName_max = 2 #stateOrProvinceName = State or Province Name (full name) #localityName = Locality Name (eg, city) 0.organizationName = Organization Name (eg, company) #organizationalUnitName = Organizational Unit Name (eg, section) commonName = Common Name (e.g. server FQDN or YOUR name) commonName_max = 64 emailAddress = Email Address emailAddress_max = 64 [req_attr] challengePassword = A challenge password challengePassword_min = 4 challengePassword_max = 20 unstructuredName = An optional company name
Die restlichen Abschnitte werden referenziert, um festzulegen, wie die ausgestellten Zertifikate verwendet werden könnne.
[usr_cert] basicConstraints = CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid, issuer keyUsage = nonRepudiation, digitalSignature, keyEncipherment [v3_req] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment [v3_ca] basicConstraints = critical, CA:true subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer keyUsage = cRLSign, keyCertSign
Die letzten beiden Abschnitte schränken die Verwendungsmöglichkeiten von Zertifikaten für OpenVPN ein.
[v3_vpn_server] basicConstraints = critical, CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment, keyAgreement extendedKeyUsage = critical, serverAuth # Extension for OpenVPN client [v3_vpn_client] basicConstraints = critical, CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always, issuer:always keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = critical, clientAuth
Wir legen ein Verzeichnis für die Zertifizierungsstelle an und darin Dateien für eine Seriennummer und eine Liste der ausgestellten Zertifikate. Andernfalls verweigert die Zertifizierungsstelle ihre Arbeit. Schließlich kopieren wir die im noch anzupassende Konfigurationsdatei.
org=illusioni mkdir $org cd $org touch index.txt touch index.txt.attr echo 01 > serial echo 01 > crlnumber
Begleitet von einer feierlichen Zeremonie erzeugen wir den Schlüssel und ein selbst-signiertes Wurzelzertifikat mit einer Gültigkeit von 10 Jahren.
orga=Illusioni openssl req \ -config openssl.cnf \ -x509 \ -new \ -nodes \ -newkey rsa:4096 \ -days 3650 \ -subj /C=DE/O=$orga/CN=$orga CA \ -keyout ca.key \ -out ca.crt
Dazu erzeugen wir eine Widerrufsliste (CRL), falls ein Schlüssel kompromittiert wird.
openssl ca -config openssl.cnf -gencrl -out ca.crl
Den Schlüssel halten wir geheim, aber das Zertifikat und die Widerrufsliste verteilen wir regelmäßig auf alle Server.
Ein Serverzertifikat wird in zwei Schritten ausgestellt: Zuerst generiert der Prinzipal einen Schlüssel und eine Anfrage (CSR), mit den zu beglaubigenden Metadaten.
orga=Illusioni zone=illusioni.de host=durmstrang year=$(date +%Y) openssl req \ -config openssl.cnf \ -new \ -nodes \ -subj "/C=DE/O=$orga/CN=$host.$zone \ -keyout $host-$year.key \ -out $host-$year.csr
Dann unterschreibt die Zertifizierungsstelle die Anfrage mit ihrem Schlüssel und stellt so das Zertifikat aus.
openssl ca \ -config openssl.cnf \ -notext \ -in $host-$year.csr \ -out $host-$year.crt
Wurzelzertifikat, Widerrufsliste sowie Serverzertifikat und -schlüssel kopieren wir auf den entsprechenden Host, der unter diesem Namen auch per Secure Shell erreichbar sein sollte.
scp ca.{crt,crl} $host-$year.{crt,key} $host:/etc/ssl
Falls der Schlüssel zu einem Zertifikat kompromittiert wurde oder es vor Ablauf der Frist aus dem Verkehr gezogen werden soll, widerrufen wir es und aktualisieren die Widerrufsliste.
openssl ca -config openssl.cnf -revoke $host-$year.crt openssl ca -config openssl.cnf -gencrl -out ca.crl
Widerrufsliste ausgeben:
openssl crl -in ca.crl -noout -issuer -lastupdate -nextupdate issuer=C = DE, ST = Some-State, O = Illusioni, CN = Illusioni Certificate Authority lastUpdate=Nov 27 11:01:46 2018 GMT nextUpdate=Dec 27 11:01:46 2018 GMT
Unter Linux werden
Schlüssel (*.key
)
Zertifikate (*.crt
),
Widerrufslisten (*.crl
) etc. grundsätzlich, als
PEM-Dateien
in der Base64-kodierten gespeichert.
Für den Austausch mit anderen Systemen müssen wir diese
gelegentlich in andere Containerformate konvertieren.
PEM Beispiel
-----BEGIN CERTIFICATE----- MIIDmTCCAoGgAwIBAgIBBTANBgkqhkiG9w0BAQsFADBgMQswCQYDVQQGEwJERTE… -----END CERTIFICATE-----
DER erzeugen
openssl x509 -outform der -in certificate.pem -out certificate.der openssl x509 -inform der -in certificate.crt -out certificate.pem
P7B erzeugen
openssl crl2pkcs7 -nocrl -certfile certificate.crt -out certificate.p7b -certfile ca.crt openssl pkcs7 -print_certs -in certificate.p7b -out certificate.pem
PFX erzeugen
openssl pkcs12 -export -inkey private.key -in certificate.crt -certfile ca.crt -out certificate.pfx openssl pkcs12 -nodes -in certificate.pfx -out certificate.pem
Alice und Bob erzeugen jeweils ein Schlüsselpaar und lassen dieses von der Zertifizierungsstelle ihres Vertrauens unterschreiben.
openssl req \ -new \ -nodes \ -subj /C=DE/O=Example/CN=Alice/emailAddress=alice@example.org \ -keyout alice.key \ -out alice.csr openssl ca -batch \ -in alice.csr \ -out alice.crt
Alice unterzeichnet ihre Nachricht mit ihrem Schlüssel.
openssl smime \ -sign \ -signer alice.crt \ -inkey alice.key \ -in plaintext.eml \ -out signed.eml
Alice verschlüsselt die Nachricht für Bob:
openssl smime \ -encrypt \ -subject Hello \ -from alice@example.org \ -to bob@example.net \ -in signed.eml \ -out encrypted.eml \ bob.crt
Bob entschlüsselt die Nachricht von Alice:
openssl smime \ -decrypt \ -in encrypted.eml -out decrypted.eml
Bob verifiziert die digitale Signatur von Alice:
openssl smime \ -verify \ -in decrypted.eml \ ...
@todo Disclaimer
Kommando | Operand | Beschreibung | |
---|---|---|---|
openssl | help | [Command] | (Optionen eines) Kommandos auflisten |
asn1parse | ASN-1-Strukturen erkunden | ||
ca | Zertifikate ausstellen und widerrufen | ||
ciphers | Verschlüsselungsverfahren auflisten | ||
cms | Certificate | S/MIME-Nachrichten im CMS-Standard bauen | |
crl | Widerufsliste verwalten | ||
crl2pkcs7 | Widerufsliste und Zertifikate verpacken | ||
dgst | File | Prüfsumme bilden | |
dhparam | Bits | Diffie-Hellmann-Paramter erzeugen | |
dsa | DSA-Schlüssel erzeugen | ||
dsaparam | DSA-Parameter erzeugen | ||
ec | EC-Schlüssel erzeugen | ||
ecparam | EC-Parameter erzeugen | ||
enc | Daten verschlüsseln und entschlüsseln | ||
engine | Engine | Treiber anzeigen | |
errstr | ErrorCode | Fehlercode nachschlagen | |
gendsa | File | DSA-Schlüssel aus Parameter-Datei erzeugen | |
genpkey | Privaten Schlüssel erzeugen | ||
genrsa | Bits | RSA-Schlüssel erzeugen | |
list | Algorithmen oder Kommandos auflisten | ||
nseq | Netscape-Zertifikatslisten untersuchen | ||
ocsp | OCSP-Status eines Zertifikats abfragen | ||
passwd | Password | Prüfsumme berechnen | |
pkcs7 | PKCS#7-Zertifikate verwalten | ||
pkcs8 | PKCS#8-Schlüssel verwalten | ||
pkcs12 | PKCS#12-Schlüsselring verwalten | ||
pkey | Private und öffentliche Schlüssel verarbeiten | ||
pkeyparam | Parameter für öffentliche Schlüssel verarbeiten | ||
pkeyutl | Operation auf öffentlichem Schlüssel ausführen | ||
prime | [Number] | Primzahl finden oder prüfen | |
rand | Count | Zufällige Bytes erzeugen | |
rehash | Dir | Symbolische Links für Zertifikate erzeugen | |
req | PKCS#10 Zertifikatsanfrage stellen | ||
rsa | RSA-Schlüssel bearbeiten | ||
rsautl | Daten signieren, ver-/entschlüsseln und verifizieren | ||
s_client | Target | TLS-Client | |
s_server | TLS-Server | ||
s_time | Zeit für Seitenaufrufe messen | ||
sess_id | SSL-Sitzung untersuchen | ||
smime | S/MIME-Nachrichten signieren, ver-/entschlüsseln und verifizieren | ||
speed | Leistungs-Selbsttest durchführen | ||
spkac | SPKAC-Werkzeug | ||
srp | SRP-Passwortdatei verwalten | ||
storeutl | Url | ? | |
ts | TSA Zeitstempel erzeugen | ||
verify | Certificate | Zertifikat verifizieren | |
version | Version ausgeben | ||
x509 | Zertifikat verwalten |
Konfigurationsdatei
Direktive | Vorgabe | Option | Beschreibung |
---|---|---|---|
[ca] | |||
default_ca | Section | -name | Konfiguration der Zertifizierungsstelle |
oid_file | File | Datei mit Objekt-Identifizierer | |
oid_section | Section | Abschnitt mit Objekt-Identifizierern | |
new_certs_dir | Path | -outdir | Verzeichnis für neue Zertifikate |
certificate | File | -cert | Wurzelzertifikat |
private_key | File | -keyfile | Schlüssel des Wurzelzertifikats |
RANDFILE | File | Zustand des Zufallszahlengenerators | |
default_days | Number | -days | Gültigkeitsdauer des Zertifikats |
default_startdate | Date | -startdate | Beginn der Gültigkeit |
default_enddate | Date | -enddate | Ablauf der Gültigkeit |
default_crl_hours | Number | -crlhours | Gültigkeitsdauer der Widerrufsliste |
default_crl_days | Number | -crldays | Gültigkeitsdauer der Widerrufsliste |
default_md | default | -md | Streufunktion |
database | File | Ausgestellte Zertifikate: index.txt | |
unique_subject | yes | Eindeutige Namen forcieren | |
serial | File | Seriennummer für Zertifikate | |
crlnumber | File | Seriennummer für Widerrufsliste | |
x509_extensions | Section | -extensions | Erweiterte Attribute des Zertifikats |
crl_extensions | Section | -crlexts | Erweiterte Attribute der Widerrufsliste |
preserve | no | -preserveDN | Reihenfolge der Attribute beibehalten |
email_in_dn | no | -noemailDN | Feld für Elektropost entfernen |
policy | Section | -policy | Abschnitt für Pflichtfelder |
name_opt | default_ca | -nameopt | Beim Ausstellen anzuzeigende Felder |
cert_opt | default_ca | -certopt | Beim Ausstellen anzuzeigende Felder |
copy_extensions | none | Umgang mit angefragten Erweiterungen | |
[req] | |||
input_password | Text | -passin | Passwort für Schlüssel (lesend) |
output_password | Text | -passout | Passwort für Schlüssel (schreibend) |
default_bits | 2048 | -newkey | Stärke für RSA-Schlüssel (512–4096) |
default_keyfile | File | -keyout | Ausgabedatei für Schlüssel |
oid_file | File | Datei mit Objekt-Identifizierer | |
oid_section | Section | Abschnitt mit Objekt-Identifizierern | |
RANDFILE | File | Zustand des Zufallszahlengenerators | |
encrypt_key | yes | -nodes | Schlüssel verschlüsseln |
default_md | Algorithm | -md | Streufunktion |
string_mask | utf8only | Erlaubte Zeichenkodierungen | |
req_extensions | Section | -reqexts | Abschnitt für erweiterte Attribute der Anfrage |
x509_extensions | Section | -extensions | Abschnitt für erweiterte Attribute des Zertifikats |
prompt | Boolean | Felder interaktiv abfragen | |
utf8 | no | Zeichenkodierung für Felder | |
attributes | Section | Dialog für Abfrage der Attribute | |
distinguished_name | Section | Dialog für Abfrage der Felder |
match | Feld muss übereinstimmen |
supplied | Feld muss vorhanden sein |
optional | Feld darf fehlen |
countryName | Länderkennung |
stateOrProvinceName | Bundesland |
localityName | Ort |
organizationName | Firmenname |
organizationalUnitName | Firmenbereich |
commonName | Benutzer- oder Hostname |
emailAddress | Elektropost-Adresse |
…{_default,_min,_max} | … Vorgabe, Mindest- und Maximallänge |