Dies ist das Gebiet der Steganographie (etwa: ,,verborgenes Schreiben``). Zu den klassischen Beispielen zählen die Zitronentinte, die erst durch Erwärmen des Blattes wieder sichtbar wird, oder (in der Antike) das Tätowieren einer Nachricht auf den glattrasierten Schädel eines Sklaven, der, sobald sein Haar nachgewachsen war, zum Empfänger geschickt werden konnte.
Glücklicherweise stehen uns heute einfachere Methoden zur Verfügung. Hier wollen wir nun einen (unverschlüsselten) Text in ein Bild einbetten, so dass man ihm die verborgene Botschaft nicht ansieht, und hernach wieder extrahieren.
Als Bildformat wählen wir dieses Mal portable graymaps (pgm), die mit den bereits bekannten portable bitmaps eng verwandt sind. Eine pgm-Datei (im Rohformat) beginnt mit der Kennung ,,P5``, es folgen (als Dezimalzahlen, jeweils durch Whitespace getrennt) die Breite w und Höhe h in Pixeln, sowie der maximale Grauwert d eines Pixels. Wir können hier davon ausgehen, dass d maximal 255 beträgt. Abgesehen davon, dass Sie diesen Wert natürlich wieder in den Header des Ausgabebildes schreiben müssen, können Sie ihn hier ignorieren.
Nach einem einzelnen, weiteren Whitespace-Zeichen (newline) folgen w x h Zeichen, wobei jedes Zeichen für ein Pixel steht und einen Wert zwischen 0 und d annehmen kann. 0 bedeutet ,,schwarz``, d ,,weiß``, und alles dazwischen sind die entsprechenden Graustufen.
Eine gültige pgm-Datei könnte also wie folgt beginnen:
P5 400 400 255 òñïíÜ#-ÀÅÃÀÀÂÁÀ¿¿¿ ...
Wenn wir nun in jedem Pixel (bzw. Bildbyte) das jeweils niedrigstwertige Bit durch ein Bit unserer Nachricht ersetzen, ändern wir den Grauwert von (statistisch) der Hälfte der Pixel um 1 / (d + 1), bei d = 255 also um 0.39 % - dies ist vom menschlichen Auge praktisch nicht wahrnehmbar, bzw. es geht im normalen Bildrauschen unter. Tabelle illustriert die Vorgehensweise.
|
Das letzte Zeichen, das Sie so einbetten, soll das Nullzeichen ('\0'
)
sein, damit Sie beim Auslesen das Ende der Botschaft
wieder erkennen können. Alle nachfolgenden Bildbytes reichen Sie
unverändert durch. Ist die Botschaft so lang, dass sie nicht
komplett im Bild untergebracht werden kann, soll das Programm eine
entsprechende Warnmeldung ausgeben.
const char *const MESSAGE = "Eine Botschaft";
Danach können Sie mit MESSAGE[i] auf das i-te Zeichen
der Botschaft zugreifen, hier also mit MESSAGE[0] auf das
'E'
, mit MESSAGE[1] auf das 'i'
usw. Erhöhen Sie den Index
i so lange, bis MESSAGE[i] == '\0'
(oder 0) ist -
genau dann nämlich haben Sie das Ende der Zeichenkette erreicht.