Der Einsatz von Steganographie hat – wie Kryptographie – Geheimhaltung und Vertraulichkeit zum Ziel. Informationen werden so verborgen, dass ein Dritter bei Betrachtung des Trägermediums keinen Verdacht schöpft. Im Gegensatz zur Kryptographie, soll eine allfällige Drittperson gar nicht merken, dass in den Daten eine verborgene Geheimbotschaft steckt. Zwei Beispiele:
- Kryptographie
- Alice schickt Bob eine mit Caesar verschlüsselte Nachricht. Eve kann mithören und erkennt sofort, dass es sich um eine verschlüsselte Nachricht handelt. Sie kennt aber den Schlüssel nicht. Die Nachricht ist also durch den Schlüssel geschützt.
- Steganographie
- Wenn aber Alice die Nachricht an Bob in einem belanglosen Gedicht versteckt, so meint Eve, es gehe nur um ein Gedicht. Sie kommt vielleicht gar nicht auf die Idee, das in dem Gedicht eine versteckte Botschaft stecken könnte.
Historisch
Das Bedürfnis eine Botschaft zu verstecken existiert seit langer Zeit. So zählt das uns bereits bekannte Beispiel mit dem Sklaven, der eine Nachricht auf den rasierten Schädel tätowiert erhält und dann die Haare nachwachsen lässt, eigentlich nicht zur Kryptographie, sondern genauer zur Steganographie. (allerdings kann man die Steganographie als Untergebiet der Kryptographie anschauen).
Weitere Beispiele wären:
- Wachstafeln, wo normalerweise die Botschaft in den Wachs geritzt wurde. Hier hatte man die geheime Botschaft unter dem Wachs ins Holz geritzt. Zur Tarnung wurde dann Wachs darüber gegossen und dort eine belangelose Nachricht hingeschrieben
- nicht oder schwer erkennbare Wasserzeichen in Papier oder Banknoten
- auch unsichtbare Tine auf Papier (z.B. mit Zitronensaft) fällt in diese Kategorie
moderne Beispiele
Ein Beispiel wo Steganographie im Alltag eingesetzt wird, ist der sogenannte Machine Identification Code. Hierbei wird bei handelsüblichen Laser- und Tintenstrahl-Druckern ein fast nicht erkennbares Wasserzeichen, bestehend aus kleinen Punkten, aufs Papier gedruckt.
In Bildern
Mit dem Computer können fast alle Datenformate manipuliert werden, um geheime Botschaften zu verstecken. Wir wollen uns anschauen, wie man in einem Bild ein anderes Bild verstecken kann.
Least significant bit (LSB)
Wenn wir uns einen roten Pixel angucken, so hat dieser z.B. die folgende Farbe rgb(255,0,0). Die erste Zahl 255
steht für den Rotanteil. Binär dargestellt gibt das 1111 1111
, also 8 Bits oder 1 Byte. So detailiert werden bei gängigen Grafikformaten die Farbkanäle abgespeichert. Wenn wir uns nun ein Byte anschauen, so ist das rechteste Bit das Least significant Bit. Für die Farbe des Pixels bedeutet das, man sieht fast keinen Unterschied, ob dieses Bit 1
oder 0
ist:
Byte des Rotkanals | Dezimaler Wert | Farbe |
---|---|---|
1111 1111 | 255 | rgb(255,0,0) |
1111 1110 | 254 | rgb(254,0,0) |
Würden wir aber ein anderes Bit umstellen, so wäre der Unterschied erkennbar:
Byte des Rotkanals | Dezimaler Wert | Farbe |
---|---|---|
1111 1111 | 255 | rgb(255,0,0) |
1111 0111 | 247 | rgb(247,0,0) |
1101 1111 | 223 | rgb(223,0,0) |
0111 1111 | 127 | rgb(127,0,0) |
Je weiter links das Bit steht, umso stärker ist sein Einfluss auf die Farbe!
Anwendung mit Bildern
Der Trick besteht nun darin, dass man in diesem Least significant Bit etwas abspeichert. So könnte man z.B. das LSB des Rotkanals verwenden, um ein Schwarz-Weiss-Bild darin zu verstecken.
Im linken Bild wird nun das letzte Bit des Rotkanals verwendet: dort wo das geheime Bild Weiss ist, wird das letzte Bit auf 1
gesetzt. Dort wo das Bild Schwarz ist, wird das letzte Bit auf 0
gesetzt. So entsteht das unten angezeigte Bild. Dieses lässt sich von Auge nicht vom Original unterscheiden, beinhaltet aber die verstecke Botschaft.
Nun kann aus der übermittelten Datei die versteckte Botschaft wieder extrahiert werden, indem das letzte Bit des Rotkanals geprüft wird. Die wiederhergestellte Nachricht sieht wie folgt aus:
mit Python programmieren
Das oben präsentierte Beispiel wurde mit den untenstehenden Python-Programmen umgesetzt. Beide Programme verwenden die Library cs20-image
die in Thonny installiert werden muss.
versteckte Nachricht einbauen
Das Programm verknüpft die beiden Dateien mushroom.png
und hidden.png
indem diese Pixel-weise durchlaufen werden. Für jeden Pixel wird das LSB in mushroom.png
auf 0
gesetzt, falls der entsprechende Pixel in hidden.png
schwarz ist, resp. auf 1
wenn er weiss ist.
import image # das image-Modul importieren
bild = image.FileImage('mushroom.png') # das Bild laden
width = bild.get_width() # die Breite des geladenen Bildes als width abspeichern
height = bild.get_height() # die Höhe als height speichern
botschaft = image.FileImage('hidden.png') # das zu versteckende Bild laden
resultat = bild.copy() # eine Kopie des Bildes erstellen
for row in range(height): # das Bild zeilenweise durchgehen – row geht von 0 bis height-1
for col in range(width): # die Zeile pixelweise durchgehen – col geht von 0 bis width-1
bild_pixel = bild.get_pixel(col,row) # den Bildpunkt an den Koordinaten (col, row) holen
botschaft_pixel = botschaft.get_pixel(col,row) # den Bildpunkt an den Koordinaten (col, row) holen
botschaft_pixel_grau = (botschaft_pixel.red + botschaft_pixel.green + botschaft_pixel.blue) /3 # grauwert des zu versteckenden Pixels
weiss = botschaft_pixel_grau > 126 # Umwandeln in schwarz-weiss
if weiss:
bild_pixel.red = 2*(bild_pixel.red // 2)+1 # beim Rot-Wert das LSB auf 1 setzen
else:
bild_pixel.red = 2*(bild_pixel.red // 2) # beim Rot-Wert das LSB auf 0 setzen
resultat.set_pixel(col,row,bild_pixel) # den Bildpunkt an den Koordinaten (col, row) mit der neuen Farbe setzen
win = image.ImageWin(width, height, "Steganographie") # ein Fenster erzeugen
resultat.draw(win) # das invertierte Bild im Fenster darstellen
resultat.save('result.png') # das invertierte Bild speichern
win.exit_on_click() # beim nächsten Mausklick aufs Fenster dieses schliessen
versteckte Nachricht extrahieren
Beim Extrahieren der versteckten Nachricht wird das Bild Pixel um Pixel durchlaufen. Wenn der Rotanteil eines Pixels eine ungerade Zahl ist, dann ist das LSB gesetzt und der Bildpunkt der versteckten Nachricht wird auf Weiss gesetzt. Im anderen Fall, wird der Pixel Schwarz dargestellt.
import image # das image-Modul importieren
bild = image.FileImage('result.png') # das Bild mit der versteckten Botschaft laden
width = bild.get_width() # die Breite des Bildes als width abspeichern
height = bild.get_height() # die Höhe als height speichern
extrahiert = bild.copy() # eine Kopie des Bildes erzeugen
for row in range(height): # das Bild zeilenweise durchgehen – row geht von 0 bis height-1
for col in range(width): # die Zeile pixelweise durchgehen – col geht von 0 bis width-1
bild_pixel = bild.get_pixel(col,row) # den Bildpunkt an den Koordinaten (col, row) holen
weiss = bild_pixel.red % 2 # das Bild ist weiss, wenn es ungerade ist (nicht durch 2 teilbar)
if weiss: # Farben setzen für Weiss
bild_pixel.red = 255
bild_pixel.blue = 255
bild_pixel.green = 255
else: # Farben setzen für Schwarz
bild_pixel.red = 0
bild_pixel.blue = 0
bild_pixel.green = 0
extrahiert.set_pixel(col,row,bild_pixel) # den Bildpunkt an den Koordinaten (col, row) mit der neuen Farbe setzen
win = image.ImageWin(width, height, "Steganographie")
extrahiert.draw(win) # die extrahierte Botschaft im Fenster darstellen
extrahiert.save('extracted.png') # die extrahierte Botschaft speichern
win.exit_on_click() # beim nächsten Mausklick aufs Fenster dieses schliessen
Hinweise
Das Programm liesse sich erweitern. Momentan wird nur der Rotkanal verwendet, dort nur das LSB. Dadurch können nur schwarz-weiss-Bilder eingebaut werden. Es wäre aber denkbar, mehrere Farbkanäle zu verwenden oder statt des letzten, auch das zweitletzte Bit für die geheime Botschaft zu verwenden.
Aufgabe
Im folgenden Bild versteckt sich ein weiteres Bild. Versuche dieses zu extrahieren, und zwar in bestmöglicher Qualität! (Farbig oder Schwarzweiss?, nur LSB? oder ev. mehrere Bits?)
Florian Heise, Druckerchannel.de, via Wikimedia Commons (PD) ↩︎