27.2 Implementierung
 
Vorüberlegungen Die Idee zur Realisierung einer einfachen Steganografie sieht so aus: Wir interpretieren die Datei, in der das Bild abgespeichert ist, als eine Folge von 'Bytes' - genauer wir fassen eine Folge von 0en und 1en zu einer Datenmenge von einem 1-byte großem Päckchen zusammen -. An bestimmten Stellen ersetzen wir ein solche Päckchen durch den ASCII-Kode eines Zeichens, das unserer zu versteckenden Botschaft entstammt. Ein  solches ASCII-Zeichen hat die Länge von einem byte.

Als Vorübung stellen wir ein Programm vor, das ein Byte aus einer Datei liest, sie in einer neuen Datei speichert, danach das nächste Byte liest und auch dieses speichert. Der Vorgang wird fortgesetzt, bis die ganze Datei gelesen und wieder gespeichert wurde. Auf der Festplatte müsste dann eine exakte Kopie der originalen Datei liegen.
 

Download:
LesenSchreiben.
java

Theseus.bmp

 

import java.io.*;

import java.util.*;

public class LesenSchreiben {



  public static void main (String[] args) throws IOException {

    String dateiNameLesen = "Theseus.bmp";

    String dateiNameSchreiben = "TheseusKopie.bmp";

    FileInputStream dateiLeser = new FileInputStream(dateiNameLesen);

    FileOutputStream dateiSchreiber = new FileOutputStream(dateiNameSchreiben);

    int z=0;

    while (z!=-1){

      z=dateiLeser.read(); //*

      dateiSchreiber.write(z); //**

    }

    dateiLeser.close();

    dateiSchreiber.close();

  }

}
Bemerkung Das Programm arbeitet natürlich nur dann korrekt, wenn sich LesenSchreiben.java (bzw. LesenSchreiben.class) und Theseus.bmp im gleichen Verzeichnis befinden. Ein Vergleich der beiden Dateien Thesues.bmp und TheseusKopie.bmp beweist, dass die beiden Dateien (inhalts)gleich sind.
 
  Um schließlich einen Text wie "Java ist Toll!" im Bild zu verstecken, müssten wir zwischen den Zeilen * und ** in gewissen Abständen ein gelesenes Zeichen durch einen Buchstaben ersetzen.
 
Download:
Steganografie.
java
import java.io.*;

import java.util.*;



public class Steganografie {

  public static void verstecken(String text, String dateiNameLesen, 

                                int start, int abstand)throws IOException{

    String dateiNameSchreiben = "h"+dateiNameLesen;

    FileInputStream dateiLeser = new FileInputStream(dateiNameLesen);

    FileOutputStream dateiSchreiber = new FileOutputStream(dateiNameSchreiben);

    int zeichen=0;

    int k=0;

    int textIndex=0;

    while (zeichen!=-1){

      zeichen=dateiLeser.read();

      if (k>start&&textIndex<text.length()&&zeichen!=-1&&k%abstand==0){

        zeichen=(int)text.charAt(textIndex);

        //System.out.print(k); Kontrollausgabe

        textIndex++;

      }

      dateiSchreiber.write(zeichen);

      k++;

    }

    dateiLeser.close();

    dateiSchreiber.close();

  }

}
  Wir haben das Verstecken in einer statischen (Klassen)methode in der Klasse Steganografie implementiert, so dass wir zum Testen des Programms eine eigene Demoklasse benötigen.
 
Download:
Steganografie
Demo.java

 
import java.io.*;



public class SteganografieDemo {



  public static void main(final String[] args)throws IOException {

    Steganographie.verstecken("Java ist toll!","Theseus.bmp",1500,100);

    System.out.println("fertig!");

  }

}
Bemerkungen In der Methode verstecken(...), die in Steganografie.java implementiert und in SteganografieDemo.java aufgerufen wird, wird der Text, der versteckt und der Namen der Bilddatei übergeben. Das neue Bild bekommt im Namen ein 'h' (=hide) vorgestellt. Der nächste Parameter gibt an welches Byte-Paket als erstes durch das  ASCII-Zeichen des ersten Buchstabens des zu versteckenden Textes ersetzt werden soll. Der letzte Parameter schließlich sagt, in welchem Abstand die Byte-Pakete aus dem Bild durch ASCII-Zeichen ersetzt werden soll. Wie man die Werte dieser Zahlen festsetzt, wollen wir später untersuchen. Nur soviel sei gesagt, sie entsprechen bei einer Verschlüsselung dem Schlüssel. Eine Anmerkung noch zu den Bedingungen in der if-Anweisung in der das Ersetzen stattfindet: Die Variable k zählt die eingelesenen Byte-Pakte. Es wird sichergestellt, dass nur dann ersetzt wird, wenn k über dem Startwert liegt und das Ende der Bilddatei noch nicht erreicht ist und dass die Byte-Pakete, die ersetzt werden, den vorgegebenen Abstand einhalten. Es kann also passieren, dass nicht der ganze Text versteckt werden kann. Das soll uns nicht stören, da es uns hier mehr um das Prinzip geht.

Warum aber soll erst ab dem 1500ten Paket ersetzt werden? Um diese Frage beantworten zu können, müssen wir etwas über das bmp-Format wissen.
 

zu 27.3 Das bmp-Format
zur Startseite www.pohlig.de  (C) MPohlig 2006