Basics: OpenSSL Tutorial


Grundlagen zu OpenSSL

Hier werden die einfachsten Befehle und Funktionen von OpenSSL beschrieben um einen kleinen Überblick zum Thema Verschlüsselung, Signierung, Zertifikate, … zu erhalten.

Einleitendes zum Thema

Was mit Kryptografie behandelt werden soll sind:

  • Integrität - Nachricht kommt nachweislich unverfälscht an.
  • Vertraulichkeit - Nachricht kann nur von der Person gelesen werden für welche sie bestimmt ist.
  • Authentizität - Der Absender ist eindeutig identifizierbar.
  • Verbindlichkeit - Der Absender kann nicht verneinen die Nachricht versendet zu haben.

Leider kann man nicht alles mit einer einzigen Methode sicherstellen.

  • Integrität - Hashes oder Signaturen
  • Vertraulichkeit - Symetrische und Asymetrische Verschlüsselung
  • Authentizität - Signatur
  • Verbindlichkeit - Signatur

OpenSSL Anwenden

Wir brauchen mindestens eine kleine und eine grössere Textdatei:

$ echo "Welcome to a very simple OpenSSL-Tutorial LAB" > plaintext.txt
$ echo for X in $(seq 9999); do echo "Welcome to a very simple OpenSSL-Tutorial LAB $X" >> plaintext_long.txt; done

Encode/Decode Base64

Mit base64 kann alles, egal ob binär oder nicht, nach ASCII codiert und wieder decodiert werden. Dabei werden immer Blöcke von 6 Bits in die Zeichen a-zA-Z0-9+/ gewandelt. Das hat den Vorteil, dass man jegliche Datei über egal welchen Kanal versenden kann da die verwendeten Zeichen in allen Charsets verfügbar sind.

$ echo "Hello OpenSSL!" | openssl enc -base64
$ echo "SGVsbG8gT3BlblNTTCEK" | openssl enc -base64 -d

Verschlüsseln

Sicherstellen: Vertraulichkeit / Confidentiallity

Um etwas zu verschlüsseln, wird das enc tool verwendet mit einem Algorithums. Für das anschliessende Entschlüsseln muss zusätzlich der Parameter -d angegeben werden.

$ echo "Hello OpenSSL!" | openssl enc -aes-256-cbc -pbkdf2
$ echo "U2FsdGVkX1/1soBuZdmhjwsPRSbdXNV0PCyBz56uldM=" | openssl enc -aes-256-cbc -a -d -pbkdf2

Hier wurde das Password pass verwendet.

Passwort in einer Datei

Die Passwort-Datei sollte immer nur von dem Besitzer les/schreibbar sein: chmod 0600 password.txt. Ansonsten können andere Benutzer auf dem selben Gerät ebenfalls damit arbeiten.

$ echo "pass" > password.txt && chmod 0600 password.txt
$ echo "Hello OpenSSL!" | openssl enc -aes-256-cbc -pbkdf2 -kfile password.txt
$ echo "U2FsdGVkX1/1soBuZdmhjwsPRSbdXNV0PCyBz56uldM=" | openssl enc -aes-256-cbc -a -d -pbkdf2 -kfile password.txt

Passwort generieren lassen

OpenSSL kann verwendet werden um Passwörter zu generieren, welche dann als Einmalpasswort verwendet werden können (siehe weiter unten).

$ openssl rand -hex -out password.bin 64

Es sollte der Parameter -hex verwendet werden und nicht -base64.

Dateien Ver-/Entschlüsseln

Gleiches Vorgehen wie beim beim Verschlüsseln von Texten, nur wird bei Dateien der Parameter -in FILE verwendet.

$ openssl enc -aes-256-cbc -pbkdf2 -in plaintext.txt -out cypher.dat
$ openssl enc -aes-256-cbc -pbkdf2 -in plaintext_long.txt -out cypher_long.dat

Und das Entschlüsseln entsprechend:

$ openssl enc -aes-256-cbc -pbkdf2 -d -in cypher.dat -out decrypted.txt
$ openssl enc -aes-256-cbc -pbkdf2 -d -in cypher_long.dat -out decrypted_long.txt

Asymmeteische Verschlüsselung

Sicherstellen: Vertraulichkeit / Confidentiallity Gebraucht von: Signierung (Authentizität und Verbindlichkeit)

Für eine Asymetrische Verschlüsseln wird ein privater und ein öffentlicher Schlüssel gebraucht. Dabei darf der private Schlüssel niemals von einer anderen Partei als dem Besitzer eingesehen oder verwendet werden. Der öffentliche Schlüssel hingegen muss von allen Parteien (und auch unbeteiligten) verwendet und eingesehen werden können.

Erstellen der Schlüssel

Für das Schlüsselmanagement wird die option genrsa und rsa verwendet. Alternativ kann auch gendsa und dsa verwendet werden wenn ein anderer Algorithmuss verwendet werden soll.

Zuerst wird ein privater Schlüssel ertsellt, anschliessend der öffentliche aus dem privaten heraus generiert/extrahiert.

$ openssl genrsa -out private.key
$ openssl rsa -pubout -in private.key -out public.pem -outform PEM

Details können folgendermassen aus den Schlüsseln herausgelesen werden:

$ openssl pkey -in private.key -noout -text 
$ openssl pkey -pubin -in public.pem -noout -text 

Dateien Ver-/Entschlüsseln

Die Schlüssel können nun verwendet werden um kleine Dateien zu ver- und entschlüsseln.

$ openssl rsautl -encrypt -inkey public.pem -pubin -in plaintext.txt -out cypher.dat
$ openssl rsautl -decrypt -inkey private.key -in cypher.dat -out decrypt.txt

Dateien die grösser sind als der öffentliche Schlüssel gehen leider nicht:

$ openssl rsautl -encrypt -inkey public.pem -pubin -in plaintext_long.txt -out cypher.dat
  139776174908736:error:0406D06E:rsa routines:RSA_padding_add_PKCS1_type_2:data too large for key size:crypto/rsa/rsa_pk1.c:124:

Um das zu machen, bracuhen wir eine Kombination aus dem Passwort und der Asymetrischen Verschlüsselung:

$ openssl rand -hex -out password.bin 64
$ openssl enc -aes-256-cbc -salt -pbkdf2 -in plaintext_long.txt -out cypher_long.enc -kfile password.bin
$ openssl rsautl -encrypt -inkey public.pem -pubin -in password.bin -out password.enc

Wir erstellen ein temporäres Passwort, verwenden dieses für die Symmetrische Verschlüsselung und verschlüsseln anschliessend das Passwort asymmetrisch.

Beide verschlüsselten Dateien können dann auf der Gegenseite verwendet werden für das entschlüsseln:

$ openssl rsautl -decrypt -inkey private.key -in password.enc -out password.dec
$ openssl enc -d -aes-256-cbc -pbkdf2 -in cypher_long.enc -out p.txt -kfile password.dec

Hashes und Signaturen

Sicherstellen: Integrität, Authentizität, Vertraulichkeit

Do not use SHA-1 or MD5 anymore, use SHA-2 (sha256, sha384, sha512, …)

Hash

Hier kann entweder OpenSSL oder ein anderes Tool verwendet werden. Hashes stellen sicher, das eine Nachricht nicht verändert wurde.

$ sha256sum password.enc
$ openssl dgst -sha256 password.enc

Um einen Hash zu verifizieren muss auf der Gegenseite der Hash ebenfalls berechnet werden und anschliessend mit dem übermittelten verglichen werden. Hashes werden meistens dazu verwendet, Signaturen und öffentliche Schlüssel zu verifizieren. Dies über einen sicheren Kanal wie Telefon oder Mündlich.

Signatur

Signaturen stellen sicher, das eine Nachricht nicht verändert wurde und das der Absender wirklich der ist, wer er ausgibt zu sein. Dazu muss ein Schlüsselpar vorhanden sein wie es auch bei der Asymetrischen Verschlüsselung verwendet wird.

Normalerweise wird eine Signatur mit Base64 noch encodiert, so dass man sie über alle verschiedenen Kanäle übermitteln kann.

$ openssl dgst -sha256 -sign private.key -out plaintext_long.bin.sign plaintext_long.txt
$ openssl enc -base64 -in plaintext_long.bin.sign -out plaintext_long.sign

Das signieren geschieht immer mit dem privaten Schlüssel. Damit verifiziert der Absender, dass die nachricht wirklich von Ihmkommt.

Das verifizieren hingegen geschieht mit dem öffentlichen Schlüssel des Absender:

$ openssl enc -d -base64 -in plaintext_long.sign -out plaintext_long.decrypt.sign
$ openssl dgst -sha256 -verify public.pem -signature plaintext_long.decrypt.sign plaintext_long.text

Zertifikate

Werden verwendet um einen Kommunikations-Kanal ab zu sichern oder auch bei EMail-Verschlüsselungen etc. Hierbei speziell ist, dass eine dritte Einheit die Identität des Absenders bestätigt, also eine Person/Organisation welcher beide Parteien vertrauen.

Self-Sign Certificate

Handelt es sich um eine einfach kommunikation, oder man kennt den Absender persönlichund vertraut ihm, kann man auch mit Self-Sign-Zertifikaten arbeiten. Hierbei bestätigt der Ersteller des Zertifikates, das er er ist.

Hat man schon einen Privaten Schlüssel, kann dieser verwendet werden.

$ openssl req -key private.key -x509 -sha256 -days 365 -new -out cert_certificate.crt

Oder man lässt einen neuen erstellen:

$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:4096 -keyout cert_private.key -out cert_certificate.crt

Um den Prozess zu vereinfachen kann der Parameter -subj "/C=CH/ST=Berne/L=Bern/O=ACME Ltd./OU=IT/CN=foobar.local/emailAddress=postmaster@foobar.local" verwendet werden.

Signing Request

Braucht man eine dritte Person um die Identität zu bestätigen, muss das Zertifikat ohne Signatur und Zeitangeben erstelt werden. Dies nennt man dann einen CSR - Certificate-signing-Request.

Hat man schon einen Privaten Schlüssel, kann dieser verwendet werden.

$ openssl req -key private.key -new -out cert_certificate.csr

Oder man lässt einen neuen erstellen:

$ openssl req -nodes -newkey rsa:4096 -keyout cert_private.key -out cert_certificate.csr

Auch hier kann der Parameter -subj ... verwendet werden.

Einen CSR signieren

Ist man selber die auserwählte Partei, welche einen CSR signieren soll, also die Identität bestätigt, macht man dies mit dem eigenen privaten Schlüssel und dem CSR von der Partei die man bestätigen soll. Das Resultat ist dann das Zertifikat welches man wieder zurück schickt.

$ openssl x509 -signkey private.key -in cert_certificate.csr -req -days 365 -out cert_certificate.crt

Zertifikat verifizieren

Als anwender eines Zertifikates sollte man dieses genau verifizieren und anschauen wer der Eigentümer ist und wer es signiert hat.

$ openssl x509 -in cert_certificate.crt -text -noout

Zertifikat erneuern

Hat man schon einen privaten Schlüssel der nicht kompromitiert ist, kann dieser verwendet werden mit dem alten Zertifikat, um ein neues zu erstellen - Self-Signed oder nicht anhand der oben verwendeten/weggelassenen Parameter.

$ openssl x509 -in cert_certificate.crt -signkey private.key -x509toreq -out cert_certificate.csr

Server Zertifikate

Braucht man für einen Server den private Key und das Zertifikat, muss man diese entsprechend aus dem PEM oder PFX extrahieren:

$ openssl pkcs12 -in certificate.pfx -nokeys -out certificate.pem
$ openssl pkcs12 -in certificate.pfx -nocerts -nodes -out private.key

Diese kann man dann z.B. bei Nginx entsprechend einbinden:

ssl_certificate /etc/nginx/certs/certificate.pem;
ssl_certificate_key /etc/nginx/certs/private.key;

Siehe auch