Hinter dem 15. Türchen des CLI-Adventskalenders verbirgt sich Verschlüsselung, ein Thema, mit dem man eine ganze Bibliothek füllen kann. Sie umfasst mehrere Bereiche der Mathematik und genug Arbeit, um abertausende MathematikerInnen ihr ganzes Leben lang beschäftigt zu halten. Mein Blogpost wird sich deswegen – hust – auf das Wichtigste beschränken.
Warum Verschlüsselung?
Hab nichts zu verstecken! Bin kein Spion/Krimineller/Regime-Kritiker! Warum soll ich mir das antun? Wo wir wieder bei Risikomodellierung wären (siehe der vorherige Artikel über Backups).
Verschlüsselung ist die einzige Form von Sicherheit, die funktioniert. Wenn ich jemandes Laptop klaue ist es egal, welches Passwort da drauf ist. Ich kann das System von einem USB-Stick booten oder die Festplatte ausbauen. Traffic mitschneiden, Backups stehlen, E-Mails lesen, … Alles nicht möglich, wenn ordentliche Verschlüsselung angewendet wird. Wenn ich Daten an Dritte weitergebe, habe ich nur sehr indirekte Kontrolle darüber, was mit diesen Daten geschieht. Wenn besagte Daten verschlüsselt sind, kann ich sie öffentlich zugänglich machen – ohne Konsequenzen.
Komplette Sicherheit?!
InfoSec-Experten zucken zusammen, wenn ich so etwas sage. Daher hier noch ein paar Einschränkungen:
- Sichere Schlüssel wählen, idealerweise aus sicheren Zufallsgeneratoren
- Schlüssel schützen, private Schlüssel niemals anderen zugänglich machen
- Keine obsoleten Algorithmen verwenden
- Nicht versuchen, eigene kryptographische Verfahren zu entwickeln
Dann ist das einzige was übrig bleibt entweder Super-Computer oder Zwang.
Das heißt im Umkehrschluss: Keine Backups, kein Mitleid. Es gibt keinen Schlüsseldienst im Cyberspace. Wer den Schlüssel verliert, ist aufgeschmissen … es sei denn, man hat sich vorbereitet …
Naja, siehe unten.
… aber wie?
Es gibt symmetrische Verschlüsselung …
openssl enc -aes-256-cbc -in erics-tagebuch.txt -out geheim.enc openssl enc -d -aes-256-cbc -in geheim.enc -out erics-tagebuch.txt
… bei der man den entsprechenden Schlüssel – ein Passwort quasi – auch aus einer Datei lesen kann.
openssl enc -aes-256-cbc -in mondbasis-plaene.txt -out extra-geheim.enc -pass file:/home/eric/.geheimer_key
Und es gibt asymetrische Verschlüsselung:
openssl genpkey -algorithm RSA -out private_key_4096.pem -pkeyopt rsa_keygen_bits:4096 openssl rsa -pubout -in private_key_4096.pem -out public_key_4096.pem openssl rsautl -encrypt -inkey public_key_4096.pem -pubin -in kompromat.tar.gz -out nichts_zu_sehen.enc openssl rsautl -decrypt -inkey private_key_4096.pem -in nichts_zu_sehen.enc -out dokumente.tar.gz
Bei symmetrischer Verschlüsselung ist derselbe Schlüssel zum Verschlüsseln und Entschlüsseln da. Bei asymmetrischer Verschlüsselung gibt es einen Public Key zum Verschlüsseln, aber Entschlüsseln geht nur mit dem Private Key.
Mit diesen Grundbausteinen können wir schon allerhand nützliche Dinge tun.
Verschlüsselte E-Mails senden
Das ist so ziemlich der häufigste Anwendungsfall. E-Mails senden mit potenziell vertraulichen Informationen. GnuPG ist hier das Werkzeug der Wahl.
gpg --full-generate-key gpg --armor --export eric@example.com > public_key.asc # Das gibt uns die id unseres Schlüssels gpg --list-keys # Die wir hier als Parameter mitgeben gpg --keyserver keyserver.ubuntu.com --send-keys key-id
Wir laden somit unseren Schlüssel auf einen öffentlichen Keyserver. Jetzt können uns andere verschlüsselte E-Mails senden, wenn sie unsere E-Mail-Adresse kennen.
Alle gängigen Mailprogramme unterstützen Verschlüsselung mit unterschiedlich hohem Benutzungskomfort.
Nachrichten signieren
Eine andere Möglichkeit die Verschlüsselung uns bietet, ist eine digitale Unterschrift, die – man könnte so argumentieren – sicherer ist als eine Physische.
gpg --detach-sign nachricht.txt
Mit Hilfe des Private Keys wird eine Prüfsumme verschlüsselt, die dann mit dem Public Key entschlüsselt werden kann (ja, das geht auch in die andere Richtung). So kann also belegt werden, dass diese Nachricht in genau diesem Wortlaut von genau diesem Empfänger kam.
gpg --verify nachricht.txt.sig nachricht.txt
Die meisten Mailprogramme haben diesen Vorgang fest integriert. Und ja, ähnliche Verfahren werden auch dazu verwendet, um zu belegen, dass z. B. Software-Updates wirklich von den entsprechenden Herstellern kommen.
Netzwerke aus Vertrauen
Und wer sagt jetzt, dass der Schlüssel auf dem Keyserver wirklich meiner ist?
Meine Freunde!
Nein, ernsthaft.
Sagen wir, ich habe einen neuen Kollegen – „Bob“ – und ich treffe ihn und er weist sich mit seinem Personalausweis aus und ich vergleiche sein Passbild mit seinem Gesicht und seine Fingerabdrücke mit … sagen wir also ich bin mir sicher, dass das wirklich der richtige Bob ist. Dann kann Bob mir mit gpg --fingerprint <a href="mailto:bob@example.com">bob@example.com</a>
den Fingerprint seines Keys geben. Und ich kann vom Keyserver seinen Key herunterladen:
gpg --keyserver keyserver.ubuntu.com --search-keys bob@example.com gpg --keyserver keyserver.ubuntu.com --recv-keys key-id
Dann kann ich vergleichen, ob der Fingerprint seines Keys mit dem Fingerprint übereinstimmt, den Bob mir gegeben hat.
gpg --fingerprint bob@example.com
Wenn sie übereinstimmen, kann ich seinen Key signieren. Ich sage also mit Brief und Siegel, dass ich – Eric … bezeuge, dass das Bob’s Key ist.
gpg --sign-key bob@example.com gpg --armor --export bob@example.com > signedkey.asc
Den signierten Key schicke ich an Bob, der ihn dann auf den Keyserver laden kann.
gpg --keyserver keyserver.ubuntu.com --send-keys key-id
Daraus entsteht, was PGP „Web of Trust“ nennt. Du kennst Alice? Du vertraust ihr? Nun, Alice hat meinen Key signiert, und ich habe Bobs Key signiert, also kannst Du Dir (relativ) sicher sein, dass die signierte E-Mail, die Du gerade bekommen hast wirklich von Bob kommt.
Und ja Kryptographie-Nerds (nicht zu verwechseln mit Crypto-Bros!) feiern bis heute Key Signing Parties.
Schlüsselboxen
Was ist jetzt, wenn ich asymmetrisch etwas verschlüsseln will, so dass mehr als eine Person es entschlüsseln kann? Magie! Hexerei! … oder einfach das digitale Äquivalent einer Schlüsselbox.
#!/bin/bash recipients=("alice@example.com" "bob@example.com" "eric@example.com") key=$(openssl rand -base64 32) gpg --batch --yes --passphrase "$key" --symmetric --cipher-algo AES256 data.tar.gz for recipient in "${recipients[@]}"; do echo "$key" | gpg --batch --yes --encrypt --armor --recipient "$recipient" > "schluesselbox-${recipient%@*}.asc" done unset passphrase
Die entsprechenden Dateien könnte ich jetzt in einen öffentlichen S3-Bucket legen, ohne mir Gedanken machen zu müssen.
Die ganze Festplatte verschlüsseln
Ja, das geht. Nein, der Computer wird davon nicht unbenutzbar. Ich habe bei mir keinen Performanceverlust bemerkt.
Leider – ACHTUNG, VORSICHT – löscht der Vorgang alle Daten auf der Festplatte. Daher muss man das vor oder bei Installation des Betriebssystems machen. Oder eben auf einem anderen Datenträger als der Hauptfestplatte.
Ich gehe jetzt in meinem Beispiel mal von einer externen Festplatte namens /dev/sdb
aus.
Erstmal mit Zufallsdaten überschreiben. Das ist zwar nicht notwendig, aber Paranoia ist die Mutter der Porzellankiste …
sudo dd if=/dev/random of=/dev/sdb bs=4M status=progress
Dann
sudo cryptsetup luksFormat /dev/sdb sudo cryptsetup open /dev/sdb tolle_verschluesselte_platte sudo mkfs.ext4 /dev/mapper/tolle_verschluesselte_platte
Dann brauchen wir natürlich noch einen Ort zum hinmounten.
sudo mkdir /mnt/tolle_verschluesselte_platte sudo mount /dev/mapper/tolle_verschluesselte_platte /mnt/tolle_verschluesselte_platte
Unmounten geht dann mit
sudo umount /mnt/tolle_verschluesselte_platte sudo cryptsetup close tolle_verschluesselte_platte
Wenn wir jetzt wollen, dass die Platte gemountet wird wenn das System hochfährt (was bedeutet, dass wir beim Booten nach dem Passwort gefragt werden), dann geht das so:
sudo echo "tolle_verschluesselte_platte UUID=$(blkid -s UUID -o value /dev/sdb) none luks" >> /etc/crypttab sudo echo "/dev/mapper/tolle_verschluesselte_platte /mnt/tolle_verschluesselte_platte ext4 defaults 0 2" >> /etc/fstab
Cryptocontainer mit doppeltem Boden
Anstelle die ganze Festplatte oder einzelne Dateien zu verschlüsseln, kann man auch eine Containerdatei (ein „Encrypted Volume“) erstellen. Diese hat eine vordefinierte Größe. Ich kann zum Beispiel eine zwei Gigabyte große Datei erstellen, die dann wie ein Monolith auf meiner Festplatte liegt und sich mounten lässt wie ein Laufwerk.
Das klingt erstmal unpraktisch, hat aber ein paar Vorteile.
- Weniger Metadaten, die leaken. Wie viele Dateien sind wirklich in dem Volume? Wann wurden sie verändert? Wie groß sind sie?
- Weniger Overhead. Ich muss nicht einzelne Dateien entschlüsseln und verschlüsseln.
- Unabhängigkeit vom Dateisystem. Ich habe die Vorteile eines Laufwerks (wenn der Strom weg ist, sind die Daten sicher) ohne, dass ich an ein physisches Laufwerk gebunden bin (wie bei Dateisystemverschlüsselung)
- Leichtes Backup. Eine Datei rüberschieben und fertig. Gut, inkrementell ist es nicht. Da wird immer die komplette Größe übertragen.
Ein weiterer Vorteil ist, dass ich ein wenig damit ausflippen darf, wie viele verschiedene Verschlüsselungsverfahren ich aneinanderkette. Dreifach verschlüsselte Dateien sind ermüdend, aber ein einzelnes Volume muss ich nur beim mounten entschlüsseln.
veracrypt -t -c --volume-type=normal --size=500M --encryption=AES-Twofish-Serpent --hash=SHA-512 --filesystem=FAT --password=HierSollteManEinSicheresPasswortReinschreiben123 --pim=0 --keyfiles="" MeinTollesVolume.vc veracrypt MeinTollesVolume.vc /media/veracrypt1
In vielen Ländern kann man rechtlich dazu gezwungen werden, Schlüssel für meine verschlüsselten Daten preiszugeben. Für plausible Deniability gibt es „Hidden Volumes“, also quasi einen unentdeckbaren doppelten Boden für unseren Koffer. Das soll vor allem Dissidenten von Diktaturen schützen, kann aber auch nützlich sein, wenn man mit Geschäftsgeheimnissen und sensiblen Daten durch einschlägige Länder reisen muss oder wenn man Hacker mit falschen Fährten in die Irre führen möchte.
veracrypt MeinTollesVolume.vc /media/veracrypt1 veracrypt -t -c --volume-type=hidden --size=100M --encryption=AES-Twofish-Serpent --hash=SHA-512 --filesystem=FAT --pim=0 --keyfiles="" --protection=protect-hidden-yes MeinTollesVolume.vc
Steganographie
Dieses png ist eine Zip-Datei.
Steganographie ist der kleine Bruder der Verschlüsselung. Verschlüsselte Daten sind nicht unterscheidbar von Zufallsdaten. Überall da wo wir große Mengen chaotischer Daten finden (z. B. in Bildern, Audioaufzeichnungen und Videos), lassen sich verschlüsselte Daten verstecken.
steghide embed -cf urlaubsfoto_003.jpg -ef geheim.txt steghide extract -sf urlaubsfoto_003.jpg
Bedauerlicherweise gibt es für DeepSound (bestes Tool für Audio-Dateien!) und OpenPuff (bestes Tool für Video-Dateien!) kein Kommandozeileninterface (Barbaren!). In unserer Not können wir unsere geheimen Daten auch einfach anhängen.
ffmpeg -i "concat:langweiliger_film.avi|geheime_daten.enc" -c copy total_unverdaechtig.avi dd if=output.avi of=geheime_daten_aus_datei.enc bs=1 skip=$(stat -c%s langweiliger_film.avi)
Das Passwort, aus dem tausend Keys entstanden
Was ist, wenn wir zehntausende Dateien mit einzigartigen Schlüsseln verschlüsseln wollen, uns das aber zu viel Overhead ist sie alle zu verwalten?
In diesem Fall können wir einen Pseudo-Random-Generator verwenden und mit einer Key Derivation Function (KDF) kombinieren und so mit einem einzigen Passwort eine beliebige Menge an sicheren Schlüsseln reproduzierbar zu generieren:
#!/bin/bash if [ "$#" -ne 1 ]; then echo "Bitte eine Zahl als Argument mitgeben: $0 <number>" exit 1 fi ZAHL=$1 GEHEIMES_PASSWORT="Test123" SALT=$(echo -n "$ZAHL" | openssl dgst -sha256 -binary) KEY=$(echo -n "$GEHEIMES_PASSWORT" | openssl enc -pbkdf2 -pass pass:"$SALT" -S "$SALT" -iter 100000 -c -a) echo "Geheimer Schlüssel: $KEY"
Mit …
chmod +x gib_mir_das_passwort.sh ./gib_mir_das_passwort.sh 23
… kann ich mir jetzt den entsprechenden Key holen.
Es funktioniert auch super als pseudo-sicherer Passwortmanager:
./gib_mir_das_passwort "animeforum.example.com"
Auch wenn ich das nicht wirklich empfehlen kann.
Passwort-Management
Was ich empfehlen kann ist pass, der Passwortmanager für die Kommandozeile!
Einfach einzurichten mit
gpg --full-gen-key gpg --lust-secret-keys --keyid-format LONG pass init "ID des Keys den ihr gerade eingerichtet habt"
… und idealerweise macht man daraus gleich ein Git-Repo.
cd ~/.password-store git init
Dann kann man Passwörter anlegen …
pass insert Mondbasis/Teamspeak
… oder generieren …
pass generate Mondbasis/Admin 32
… und dann ausgeben …
pass Mondbasis/Teamspeak
… oder in die Zwischenablage kopieren:
pass -c Mondbasis/Admin
Es bleibt dann für 45 Sekunden in der Zwischenablage.
pass edit Mondbasis/Animeforum pass rm Mondbasis/Dockerhub
… tun übrigens ziemlich genau das was man erwartet.
Nun haben wir leider Metainformationen preisgegeben durch unsere Ordner- und Dateienbenamung. Anstelle eines Git-Repos (oder zusätzlich dazu?) könnte man um dem ein wenig entgegenzusteuern das pass-Repo in ein Veracrypt-Volume stecken. Oder in ein Hidden Volume in einem Veracrypt-Volume, das wir in eine Videodatei hinein-steganographieren, die wir in ein verschlüsseltes zip-Archiv legen, das wir auf einer verschlüsselten Festplatte ablegen.
Verschlüsselung lässt sich so hoch stapeln wie die eigene Paranoi … äh … das eigene Sicherheitsempfinden es verlangt.
WYSIWYG – „What you see is what you get“ – ein Prinzip, das bis in die frühen 70er zurückgeht, als Xerox PARC Bravo herausbrachte und mit Textverarbeitungsprogrammen aufräumte, die alle ihre eigene Markup-Sprache zur Formatierung mitbrachten. Meine Generation kämpfte daraufhin lange mit Programmen wie Microsoft Word, in denen Dinge häufiger mal aus unerfindlichen Gründen zerbrochen sind.
WYSIWYM – „What you see is what you mean“ – ist die nächste Maxime. Die meisten meiner KollegInnen sind super zufrieden mit Markdown. Einfach ein paar Überschriften und Links ohne viel visuellem Ballast. Genauso wie die Konsole eigentlich.
Eine GUI zu benutzen ist oft wie Essen in einem Land zu bestellen, dessen Sprache ich nicht spreche. Ich zeige verwirrt auf eine Speisekarte bis ich Dinge bekomme, die sich hoffentlich mit meiner Verdauung vertragen. Waren die Einstellungen unter Datei? Unter Bearbeiten? Wo kann ich hier meinen API-Key hinterlegen? Habe ich diese Option überhaupt?
„Aber Eric, als ob Du jedes Kommandozeilenwerkzeug so schnell benutzen kannst wie eine Teekanne!“ Wollen wir die Zeit stoppen? Einmal die Manpages aufmachen und Volltextsuche. Einmal ChatGPT fragen. Eine schnelle DuckDuckGo-Suche. Auch bei den krassen Hipster-Javascript-Tools, die einfach ihre README.md in die Mapage copy-pasten (ein ganz eigener Rant), kann ich im Source Code schnell die verfügbaren Parameter nachschlagen.
Im Vergleich dazu strenge ich bei GUI-Tutorials meine Augen an, um eine Reise aus Screenshots nachzuverfolgen.
Das ist aber gar nicht mein Punkt.
Mein Punkt ist, dass ich Kommandozeilen-Werkzeuge wie Legosteine ineinanderstecken kann. Mein Punkt ist, dass die Shell (wie schon erwähnt) eine Programmiersprache ist, die mit jedem installierten Programm mächtiger wird. Ich kann dann Befehle in einer Schleife aufrufen oder filtern oder den Output eines anderen Programms nehmen, um die Konfiguration für dieses hier zu generieren. Auf der Kommandozeile habe ich immer Optionen. Und wenn ich Optionen habe bin ich niemals hilflos.
Zum Abschied noch den Unix-Koan, der Inspiration für die heutige Weisheit war.
Schreibe einen Kommentar