Auf die Implementation kommt es an

Verschlüsselungsdemonstration: ECB vs. CBC. Maximale Sicherheit durch richtige Methodenwahl.

Auf die Implementation kommt es an
Photo by Markus Winkler / Unsplash

Ich habe vor Kurzem einen Beitrag über openssl geschrieben, da ich einmal gefragt wurde, wie man Dateien verschlüsseln kann, und sie dann unter jedem Betriebssystem dann auch wieder entschlüsseln. Da ich die Konsole sehr gern nutze, kam mir natürlich sofort openssl in den Sinn.

Nützliche Anwendungen für openssl
Umfassende Anleitung zu OpenSSL: Von Grundlagen, Benchmarking, Zertifikatsverwaltung bis zur Verschlüsselung und S/MIME.

In diesem Artikel mache ich ein Experiment zur Verschlüsselung einer BMP-Datei (meister-security-logo.bmp). Ziel ist es, die Auswirkungen verschiedener Verschlüsselungsverfahren auf die Datei zu untersuchen. Dabei wird insbesondere der Unterschied zwischen den Modi ECB und CBC des AES-128-Algorithmus beleuchtet. Am Beispiel eines Bildes kann man sehr schnell erkennen, ob die Verschlüsselung gut oder schlecht ist.

Dies soll die Eingangsdatei sein:

Original-Datei

Extraktion des BMP-Headers

Eine BMP-Datei beginnt mit einem 54 Byte großen Header, der wichtige Metadaten über das Bild enthält. Dazu gehören Informationen wie Bildgröße, Farbtiefe und die verwendete Komprimierungsmethode.

Um den Header zu extrahieren und separat zu speichern, wird der folgende Befehl verwendet:

head -c 54 meister-security-logo.bmp > bmp-header

Dieser Befehl liest die ersten 54 Bytes der Datei meister-security-logo.bmp und speichert sie in einer neuen Datei namens bmp-header. Diese Datei dient als Grundlage für die folgenden Schritte, in denen die verschlüsselten Bilddaten wieder mit einem gültigen Header kombiniert werden.

Kopie des Headers für die verschlüsselte Datei

Nachdem der Header extrahiert wurde, wird eine Kopie davon erstellt. Diese Kopie dient als Ausgangspunkt für die Erstellung der Datei, die die verschlüsselten Bilddaten enthalten wird. Der Befehl hierfür lautet:

cp bmp-header meister-security-header-crypted.bmp

Durch diesen Befehl wird eine neue Datei meister-security-header-crypted.bmp angelegt, die zunächst identisch mit der zuvor erstellten bmp-header-Datei ist. An diese Datei werden später die verschlüsselten Bilddaten angehängt, sodass eine gültige, aber verschlüsselte BMP-Datei entsteht.

Berechnung der reinen Bilddatengröße

Um die Größe der reinen Bilddaten zu ermitteln, muss die Gesamtgröße der BMP-Datei abzüglich der Headergröße (54 Bytes) berechnet werden. Zuerst wird die Gesamtgröße der Datei mit wc -c ermittelt:

wc -c meister-security-logo.bmp
1920054

Die Ausgabe zeigt, dass die Datei meister-security-logo.bmp 1.920.054 Bytes groß ist. Davon sind die ersten 54 Bytes der Header. Um die Größe der reinen Bilddaten zu berechnen, wird folgende Rechnung durchgeführt:

echo $((1920054-54))
1920000

Das Ergebnis dieser Berechnung ist 1.920.000 Bytes. Diese Zahl gibt die Größe der reinen Bilddaten ohne Headerinformationen an.

AES-128-ECB-Verschlüsselung

Der nächste Schritt ist die Verschlüsselung der gesamten BMP-Datei, einschließlich des Headers, mit dem AES-128-Algorithmus im ECB-Modus. Der verwendete Befehl lautet:

openssl enc -aes-128-ecb -e -in meister-security-logo.bmp -out temp.bin -K 00112233445566778889aabbccddeeff -iv 0102030405060708

Es ist zu beachten, dass der ECB-Modus keinen Initialisierungsvektor (IV) benötigt. Daher gibt OpenSSL eine Warnung aus, dass der angegebene IV ignoriert wird. Bei der Verschlüsselung im ECB-Modus werden gleiche Klartextblöcke in gleiche Chiffretextblöcke umgewandelt. Da BMP-Dateien oft eine hohe Redundanz aufweisen, führt dies im ECB-Modus zu erkennbaren Mustern in den verschlüsselten Daten.

Zusammenbau der verschlüsselten Bilddaten

Nach der Verschlüsselung der gesamten Datei im vorherigen Schritt werden nun die verschlüsselten Bilddaten extrahiert und an die zuvor erstellte Kopie des Headers angehängt. Hierfür wird folgender Befehl verwendet:

tail -c 1920000 temp.bin >> meister-security-header-crypted.bmp

Dieser Befehl entnimmt die letzten 1.920.000 Bytes aus der temporären Datei temp.bin, welche die verschlüsselte Version der BMP-Datei enthält. Diese 1.920.000 Bytes entsprechen den reinen Bilddaten. Durch das Anhängen (>>) dieser Bytes an die Datei meister-security-header-crypted.bmp wird eine neue BMP-Datei erzeugt. Diese neue Datei besitzt den originalen, unveränderten Header, gefolgt von den mit AES-128-ECB verschlüsselten Bilddaten. Das Bild sieht nun so aus:

Schlecht verschlüsselte Datei

Besonders gut ist die Datei offensichtlich nicht verschlüsselt. Der Inhalt ist noch deutlich zu erkennen.

AES-128-CBC-Verschlüsselung

Der gesamte Vorgang wird nun mit dem AES-128-Algorithmus im CBC-Modus wiederholt. Zunächst wird wieder eine Kopie des originalen Headers erstellt:

cp bmp-header meister-security-header-crypted-2.bmp

Anschließend erfolgt die Verschlüsselung der gesamten BMP-Datei mit folgendem Befehl:

openssl enc -aes-128-cbc -e -in meister-security-logo.bmp -out temp.bin -K 00112233445566778889aabbccddeeff -iv 0102030405060708

Im CBC-Modus wird ein Initialisierungsvektor (IV) benötigt. Da der angegebene IV nicht die korrekte Länge für AES-128 hat (er müsste 16 Bytes lang sein), gibt OpenSSL eine Warnung aus und füllt den IV mit Nullen auf. Der CBC-Modus verwendet eine Blockverkettung, bei der jeder Klartextblock vor der Verschlüsselung mit dem vorherigen Chiffretextblock XOR-verknüpft wird. Dadurch wird die Diffusion erhöht und es entstehen keine erkennbaren Muster wie im ECB-Modus.

Ersetzen der verschlüsselten Bilddaten (CBC)

Analog zum Vorgehen beim ECB-Modus werden nun die verschlüsselten Bilddaten aus der mit AES-128-CBC verschlüsselten Datei extrahiert und an die Kopie des Headers angehängt. Der Befehl ist identisch zum vorherigen Schritt:

tail -c 1920000 temp.bin >> meister-security-header-crypted-2.bmp

Auch hier werden die letzten 1.920.000 Bytes aus der temporären Datei temp.bin entnommen, die nun die mit AES-128-CBC verschlüsselte Version der BMP-Datei enthält. Diese Bytes, die den reinen Bilddaten entsprechen, werden an die Datei meister-security-header-crypted-2.bmp angehängt. Das Ergebnis ist eine neue BMP-Datei mit dem originalen Header, gefolgt von den mit AES-128-CBC verschlüsselten Bilddaten.

Dies führt zu dieser Datei:

Gut verschlüsselte Datei

Vergleich der Verschlüsselungsmodi (ECB vs. CBC)

Durch das beschriebene Experiment wird der Unterschied zwischen den Verschlüsselungsmodi ECB und CBC deutlich. Im ECB-Modus führt die hohe Redundanz in den Bilddaten zu wiederholten Mustern im Chiffretext. Diese Muster sind visuell erkennbar, wenn man die verschlüsselte Datei als Bild interpretiert. Im Gegensatz dazu sorgt der CBC-Modus durch die Blockverkettung für eine bessere Diffusion. Selbst bei hoher Redundanz im Klartext sind im Chiffretext keine Muster mehr erkennbar.

Erstellung einer erkennbaren, aber verschlüsselten BMP-Datei

Ein interessantes Ergebnis des Experiments ist, dass die erzeugten Dateien meister-security-header-crypted.bmp und meister-security-header-crypted-2.bmp trotz der Verschlüsselung der Bilddaten von BMP-Viewern als gültige BMP-Dateien erkannt werden. Dies liegt daran, dass der Header in beiden Fällen intakt und unverändert bleibt. Der Header enthält alle nötigen Informationen, damit ein BMP-Viewer die Datei korrekt interpretieren kann. Die Bilddaten selbst sind jedoch unlesbar, da sie verschlüsselt wurden.

Fazit

Wenn ich mich mit Usern unterhalte, die mir versuchen zu erklären, das AES-128 die beste Verschlüsselung sei, dann kann ich es mir manchmal nicht verkneifen Rückfragen zu stellen. Denn wie so oft geht es bei Verschlüsselung eben auch um die Implementation - was ich mit diesem Beitrag hoffentlich deutlich erklären konnte.