Praktische Kryptographie mit openssl

Hier werden die Kryptographische Grundlagen um praktische Übungen mitopenssl (Schlüsselerzeugung, digitale Signatur, Ver-/Entschlüsselung, Zertifikatsantrag) ergänzt.

openssl

"OpenSSL is a robust, commercial-grade, and full-featured toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols. It is also a general-purpose cryptography library." - von der openssl-Webseite.

Beschreibung aus der Manpage

DESCRIPTION
   OpenSSL is a cryptography toolkit implementing the Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) network protocols and related cryptography standards required by them.

   The openssl program is a command line tool for using the various cryptography functions of OpenSSL's crypto library from the shell.  It can be used for

    o  Creation and management of private keys, public keys and parameters
    o  Public key cryptographic operations
    o  Creation of X.509 certificates, CSRs and CRLs
    o  Calculation of Message Digests
    o  Encryption and Decryption with Ciphers
    o  SSL/TLS Client and Server Tests
    o  Handling of S/MIME signed or encrypted mail
    o  Time Stamp requests, generation and verification
  • Sehen Sie sich die Manpage zu openssl an: man openssl

  • Mit openssl help können Sie sich die openssl Kommandos auslisten lassen.

  • Mit openssl help kommando erhalte Sie die Beschreibung, wie ein spezielles Kommando benutzt wird, z.B.:

In [1]:
openssl version -d
OPENSSLDIR: "/usr/lib/ssl"
In [2]:
apt-cache search libssl | grep SSL
perl-openssl-defaults - version compatibility baseline for Perl OpenSSL packages
cl-plus-ssl - Common Lisp interface to OpenSSL
libssl-ocaml - OCaml bindings for OpenSSL (runtime)
libssl-ocaml-dev - OCaml bindings for OpenSSL
libssl-utils-clojure - library for SSL certificate management on the JVM
r-cran-openssl - GNU R toolkit for encryption, signatures and certificates based on OpenSSL
In [3]:
openssl version
OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
In [4]:
openssl help genrsa
Usage: genrsa [options] numbits

General options:
 -help               Display this summary
 -engine val         Use engine, possibly a hardware device

Input options:
 -3                  (deprecated) Use 3 for the E value
 -F4                 Use the Fermat number F4 (0x10001) for the E value
 -f4                 Use the Fermat number F4 (0x10001) for the E value

Output options:
 -out outfile        Output the key to specified file
 -passout val        Output file pass phrase source
 -primes +int        Specify number of primes
 -verbose            Verbose output
 -traditional        Use traditional format for private keys
 -*                  Encrypt the output with any supported cipher

Random state options:
 -rand val           Load the given file(s) into the random number generator
 -writerand outfile  Write random data to the specified file

Provider options:
 -provider-path val  Provider load path (must be before 'provider' argument if required)
 -provider val       Provider to load (can be specified multiple times)
 -propquery val      Property query used when fetching algorithms

Parameters:
 numbits             Size of key in bits

Erzeugen eines Private/Public Keypaares mit openssl

Zwei Bash-Variablen für Dateinamen:

In [5]:
# Privacy Enhanced Email (pem) Format
private_keyfile="private.pem"
public_keyfile="public.pem"

Erzeugung des privaten Schlüssels interaktiv auf der Kommandozeile:

  • genrsa ist das (Unter-)Kommando
In [6]:
openssl genrsa -out ${private_keyfile} 2048

Oft ist es sinnvoll den Private-Key mit einem symmetrischen Verschlüsselungsalgorithmus zu schützen. Der Befehl ist dann

openssl genrsa -aes128 -out ${private_keyfile} 2048

  • aes128 verschlüsselt den Private Key mit einem symmetrischen Verschlüsselungsalgorithmus (AES)

Dabei wird eine Passphrase festgelegt, die später auch immer interaktiv eingegeben werden muss, wenn der Private-Key verwendet wird. Die Passphrase dient dazu, den privaten Schlüssel zu schützen.

Hinweis: Der private Schlüssel muss gut verwahrt werden und darf auf keinen Fall weitergegeben werden etc. Hier nur zur Demonstration, wie ein private Keyfile aussieht. Diesen verwende ich aber natürlich nicht.

In [7]:
cat ${private_keyfile} 
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCo6qrrivrkJEtJ
m6uh82UpHwNh46ly4GFJBC7vA6QmPDBOIdrgSyYxicYjpRHTMefhY5YbMV3fGxsl
6FjC1poMxQYCvHHYkwSxfaFsOFz9tk+E0t/eGNwgusy+P9jQrKqoPJ6BjOTQ/5jq
AMwq22Kh7YatuONUOKMSHdF4j/SEpqlNIQOid1l6Y6audu6dd5yVHg83VNkH8If0
EMT8OaBih5Oy8xHgHST4qndLWbO7CZOjOVUn1XfEXxFPMqVcQmPZC7ZRLZ3HW5O1
6/Vw0goiupoqhriQvVSXZLia3n7RInjdicfBCTF8Vmrp884HnyL/ju8pVESzW27P
ibs5KOjTAgMBAAECggEAReNeF3mXx8f6fHiToTyuqL5jrF9BDz4mEktQTeUQSB+U
Due0AyQkp89ssvfLsbmOyrLk+thIkhRJfbwt6WNYNptYGs60PdrKUNN9c+S4GOMS
8I49QMvBXCtdpgONpf0i2NvH6ysLyytNrdfpoXvGyd+YXw1FxWVvlwHOVtcc4LrU
0UpemUbnPZZGq4hQd8uSVpeIhmdWPN4NsJJxqF1DimD8ODirCeYUFSZsuHIPVYSg
hm4N3raaX5sYEzt5UdSDwfTu4Tjc+q77BLFU8zk0w/+RrUaLFUGL83KJabyJPf0t
nw2hBuLKssavAL4YjZunRyXl0eRN9dP2yFx0sON+RQKBgQDpMRpIDg4wKvgFkbSW
V7/MEydSU1P2Olvx29THVSCk8fXumIEsmfVHy9IcMsjq313DIaq/7tb5Ds08VlA2
2uIHam4f5ZpbnyHeGrfqUguJsOvkKgkzrQh+3IRyqoAGdb4nxx2To3rS6Grk/3V/
kNxK7kDO5kkqClxWLJzFYB1n5wKBgQC5cC1/uMhXcu7Vo8Hst+XzrJimyiVGeu4p
sg/B04mdhx5lhTJIpUmta4KlZgqQCT+XPsxZMscErSmknKFgl09EYsnvFuoly68n
mxicadXZLLzsGdGVfSMZpjbfehT/74OSCRDdbVvTZE9HoQptrdCda+Bs71xuXkyb
SLCrRPWqNQKBgBv04BK9ZKQPsrZwNndDw+HCdhdfmBRQAM/pLARNx2EfBP362Jmx
R3+5BtKMoBvQdZw8QA1MpAct6BsQugMpkKmU7+jxDOVpGZVYHK6B8ZIrXMx44auJ
VhhndZWNrVWY7hg0ve4CTmpUpOQZYEvP4Sk2kRx87U6V+WX3aUAcesoHAoGARKK5
pHl/Zaa7scV/5J8YdL2gbrOJYnHjrvkiDeq/F9hILulC+FJ9V7vgSlnfdPqHV/K9
bhJ2SUvSiwQSUw8OHtC1z1Ha7oxaUz17uYEOzuhZMMZJpZwAnuC/lK26EhTTzPyg
CmUMxMxu76Myme/otCuWkJtzycILdrpL8ch/aTUCgYBACtZevGSbzymwphT5H7b7
plASmJkjpAJb/74f8HaSfq3QraWOmIWzSg0c2AEQnVrxa7efIusO79u1mAPjooUE
W+/Z9LW1d4mLN0Y4fsfgOlKXYlu4PqWRzJ1LcqcRLYKgTWE411euWy1WXLiHfWcu
mIemMcI/zgnFieu/2rCGUQ==
-----END PRIVATE KEY-----

Erzeugen des korrespondierenden öffentlichen Schlüssels. Falls der Private-Key mit AES verschlüsselt wurde, hier die Passphrase abgefragt:

In [8]:
openssl rsa -in ${private_keyfile} -pubout -out ${public_keyfile}
writing RSA key
In [9]:
cat ${public_keyfile} 
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqOqq64r65CRLSZurofNl
KR8DYeOpcuBhSQQu7wOkJjwwTiHa4EsmMYnGI6UR0zHn4WOWGzFd3xsbJehYwtaa
DMUGArxx2JMEsX2hbDhc/bZPhNLf3hjcILrMvj/Y0KyqqDyegYzk0P+Y6gDMKtti
oe2GrbjjVDijEh3ReI/0hKapTSEDondZemOmrnbunXeclR4PN1TZB/CH9BDE/Dmg
YoeTsvMR4B0k+Kp3S1mzuwmTozlVJ9V3xF8RTzKlXEJj2Qu2US2dx1uTtev1cNIK
IrqaKoa4kL1Ul2S4mt5+0SJ43YnHwQkxfFZq6fPOB58i/47vKVREs1tuz4m7OSjo
0wIDAQAB
-----END PUBLIC KEY-----

Digitale Signatur mit openssl

Recap: Mittels einer Digitalen Signatur lässt sich eine Nachricht unterschreiben mittels des privaten Keys und der Passphrase.

Dann kann mittels des öffentlichen Schlüssels überprüft werden, ob die Signatur gültig ist.

In [10]:
# Nachricht in Datei
filename="my_message.txt"
echo -e "Das ist meine Nachricht: Ja, glaubt mir.\nIch habe immer Recht." > $filename

Unterschreiben (Signieren) einer Nachricht mittels eines privaten Schlüssels

Die Nachricht kann mit dem private Key signiert werden. Falls der Private-Key mit AES verschlüsselt wurde, muss hier natürlich wieder die Passphrase interaktiv eingegeben werden:

In [11]:
signature_file="signature"
In [12]:
openssl dgst -sha256 -sign $private_keyfile -out binary.$signature_file.sha256 $filename

Nebenbemerkung: Binärdateien können mittels hexdump angezeigt werden

In [13]:
hexdump binary.$signature_file.sha256
0000000 1160 2fac 4321 0dcf 75f7 3621 c563 9e6f
0000010 c032 34c3 1ebb 06c6 ccf4 6316 ae36 1749
0000020 7365 88d6 0cf7 f5c8 9dd5 efc8 4d2a 77cf
0000030 7705 c709 8f6f cbf4 e0c1 d373 3544 ca30
0000040 7f67 206b 374f 304c 374f facb 986e 6315
0000050 f490 6b86 f05d 6f23 3dae 818f 809e fe0d
0000060 3998 f583 069e 2db5 df2a 2ed8 ede5 1432
0000070 c77e e71b 59a8 6a07 081b b769 df47 1527
0000080 8cd4 4288 5163 f6a7 4e7a 7353 d6e0 9539
0000090 968d ea30 8fe3 03b4 9f1f 98d5 224a a89e
00000a0 0018 cbbd 8d5b 8518 d07b 1159 fdea 8899
00000b0 da9b a6f4 cc18 ea54 3996 a743 92fd 80b6
00000c0 05d2 8135 7dae aad2 abec 3520 225c 7f79
00000d0 1e95 83a5 3b4d 99f5 cc42 6a15 520a d63b
00000e0 1fd6 f28c c02d bd02 0415 ae76 9c8c 7184
00000f0 fb0b e291 b0b6 a781 04e2 5190 d578 1366
0000100

Die Signatur kann man auch mittels Base64 in eine ASCII-Textdatei umwandeln:

In [14]:
openssl base64 -in binary.$signature_file.sha256 -out $signature_file
In [15]:
cat $signature_file
YBGsLyFDzw33dSE2Y8VvnjLAwzS7HsYG9MwWYzauSRdlc9aI9wzI9dWdyO8qTc93
BXcJx2+P9MvB4HPTRDUwymd/ayBPN0wwTzfL+m6YFWOQ9IZrXfAjb649j4GegA3+
mDmD9Z4GtS0q39gu5e0yFH7HG+eoWQdqGwhpt0ffJxXUjIhCY1Gn9npOU3Pg1jmV
jZYw6uOPtAMfn9WYSiKeqBgAvctbjRiFe9BZEer9mYib2vSmGMxU6pY5Q6f9kraA
0gU1ga590qrsqyA1XCJ5f5UepYNNO/WZQswVagpSO9bWH4zyLcACvRUEdq6MnIRx
C/uR4rawgafiBJBReNVmEw==

Validieren

Überprüfen, ob die Signatur mit der Datei zusammenpasst:

Eventuell muss man die binäre Signatur für openssl aus der Textdatei erzeugen:

openssl base64 -d -in $signature_file -out binary.$signature_file.sha256

Das eigentliche Verifizieren erfogt mittels:

In [16]:
openssl dgst -sha256 -verify $public_keyfile -signature binary.$signature_file.sha256 $filename
Verified OK

Nachrichten verschlüsseln und entschlüsseln

Verschlüsseln der Nachricht mit dem Public-Key:

Hinweis: openssl rsautl ist in neueren OpenSSL-Versionen als veraltet (deprecated) markiert; der empfohlene Nachfolger ist openssl pkeyutl (z.B. openssl pkeyutl -encrypt -pubin -inkey $public_keyfile -in $filename -out $filename.enc). RSA kann zudem nur Daten verschlüsseln, die kürzer als der Schlüssel sind. In der Praxis wird deshalb hybrid verschlüsselt: RSA verschlüsselt nur einen zufälligen symmetrischen Schlüssel, mit dem die eigentlichen Daten symmetrisch verschlüsselt werden.

In [17]:
openssl rsautl -encrypt -inkey $public_keyfile -pubin -in $filename -out $filename.enc
The command rsautl was deprecated in version 3.0. Use 'pkeyutl' instead.
In [18]:
hexdump -C $filename.enc
00000000  5d bf fa 69 31 ad 88 a5  06 2a 90 76 3b a6 8d 19  |]..i1....*.v;...|
00000010  e8 ef 62 c4 3d 5b dc cc  0e fe 87 9c d8 71 c2 2c  |..b.=[.......q.,|
00000020  e2 0b 89 39 b6 d5 fc 04  b3 59 d1 35 36 5d 3e 97  |...9.....Y.56]>.|
00000030  e3 0c 0a 2c ee 27 c9 f0  50 db 08 b7 7c b3 5e 5b  |...,.'..P...|.^[|
00000040  49 8c ee cf d3 f3 b5 ce  e7 fa b6 99 5b fa fc 22  |I...........[.."|
00000050  c7 96 99 0c 63 2c 67 3d  90 12 3b 14 d0 13 2a 70  |....c,g=..;...*p|
00000060  86 52 72 11 0b c9 3c 02  38 3a 96 69 d5 10 78 06  |.Rr...<.8:.i..x.|
00000070  a5 2c 7a 70 6a e9 70 5d  0c 58 6d f4 f0 24 3d 4e  |.,zpj.p].Xm..$=N|
00000080  41 0b 2a b6 e8 15 2b 2a  0b 3f 7c 46 c1 e7 b2 22  |A.*...+*.?|F..."|
00000090  f0 ab a3 eb 89 d6 44 28  1f 9d 03 a6 47 db 3e e8  |......D(....G.>.|
000000a0  34 f2 20 41 c6 b1 bb 8f  d2 d9 de 1a 74 be 3a 9a  |4. A........t.:.|
000000b0  b1 b4 5e 0f 23 2c d6 41  74 15 04 a4 40 54 df 1c  |..^.#,.At...@T..|
000000c0  3a 5a dd 86 f8 12 c7 dd  00 61 9b be a4 4e 7c 3c  |:Z.......a...N|<|
000000d0  5f de 00 81 ab 6a c4 7d  11 a4 1e 32 48 15 3a fb  |_....j.}...2H.:.|
000000e0  49 90 4a 9e 09 6a ef a0  a8 be a5 64 c9 6c 7f be  |I.J..j.....d.l..|
000000f0  bb ca 21 32 7e d9 3b 43  62 aa 26 2d 72 b1 ba 63  |..!2~.;Cb.&-r..c|
00000100
In [19]:
openssl rsautl -decrypt -inkey $private_keyfile -in $filename.enc > top_secret.txt
The command rsautl was deprecated in version 3.0. Use 'pkeyutl' instead.
In [20]:
cat top_secret.txt
Das ist meine Nachricht: Ja, glaubt mir.
Ich habe immer Recht.

Aufgabe (optional)

  1. Suchen Sie sich ein/e Kommiliton(en/in) und spielen Sie eine asymmetrisch verschlüsselte Kommunikation per verschlüsselter Text-Datei mit openssl über einen ungeschützen Kanal (z.B. per Email-Anhänge) durch:
  • Erzeugen Sie zuerst die Private-Public Keys mit openssl. Wieviele Schlüsselpaare benötigen Sie?
  • Public-Key Austausch: Tauschen Sie die Schlüssel (vertrauenwürdig) aus.
    • Welche Schlüssel erhält der Kommunikationspartner?
    • Wieso ist der Austausch in der Praxis bei Kommunikationspartnern, die sich z.B. nicht persönlich treffen können, schwierig? Was ist das Problem dabei? Welche Lösungen wurden hierfür entwickelt?
  • Schreiben Sie eine verschlüsselte Nachricht und übermitteln Sie diese an die/den Kommunikationspartner/in. Diese/r soll mit einer verschlüsselten Nachricht antworten(, die der Empfänger natürlich entschlüsseln kann).
  1. Wie kann dabei gewährleistet werden, dass eine Nachricht wirklich von ihrem Kommunikationspartner stammt. Beachten Sie dabei, dass der Public-Key im Allgemeinen jedem/jeder bekannt ist. Wie müssen Sie Kommunikations-Schema erweitern, dass dies gewährleistet wird. Spielen Sie dies auch dann wieder (wie oben) durch.

Hinweis: Schreiben Sie Shellskripte, in denen Sie die openssl-Befehle verwenden, um die Benutzung einfacher zu machen.

Datei für Zertifikatsantrag bei CA

Mit Hilfe des openssl-Kommandos req lässt sich eine Datei für einen Zertifikatsantrag bei einer CA erstellen:

openssl req -new -sha256 -key ${private_keyfile} -out ${csr_file}

Der CSR wird mit dem privaten Schlüssel signiert; der öffentliche Schlüssel wird daraus abgeleitet und in den CSR eingebettet. csr_file ist ein selbst gewählter Dateiname, z.B. csr_file="request.csr".

CSR steht für Certificate Signing Request

mehr hierzu siehe z.B. https://www.keycdn.com/blog/openssl-tutorial

Aufgabe (optional)

Erzeugen Sie ein Self-Signed Certificate, wie hier beschrieben https://help.ubuntu.com/community/OpenSSL.