unit uMainFrm;
interface (* ==================================================================== *) uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, Menus, uAboutBox, uStegHide;
type TMainFrm = class(TForm) MainMenu: TMainMenu; Datei1: TMenuItem; OpenMenuE: TMenuItem; SaveMenuE: TMenuItem; N1: TMenuItem; EndMenuE: TMenuItem; AboutMenuE: TMenuItem; Funktionen1: TMenuItem; DechiffrierenMenuE: TMenuItem; ChiffrierentMenuE: TMenuItem; Image: TImage; DataBitLbl: TLabel; DataBitCBox: TComboBox; MaxTextLbl1: TLabel; BmpOpenDialog: TOpenDialog; TextLengthLbl1: TLabel; TextLengthLbl2: TLabel; MaxTextLbl2: TLabel; N2: TMenuItem; BildanzeigenMenuE: TMenuItem; BmpSaveDialog: TSaveDialog; GeheimTextMemo: TMemo; TextladenMenuE: TMenuItem; TextspeichernMenuE: TMenuItem; TxtOpenDialog: TOpenDialog; TxtSaveDialog: TSaveDialog; ClearTextBtn: TMenuItem; procedure LadeBmp(Sender : TObject); // lädt des bmp bei Auswahl von Datei/Laden procedure LadeTextDatei(Sender : TObject); procedure EndMenuEClick(Sender: TObject); procedure AboutMenuEClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure ChiffrierentMenuEClick(Sender: TObject); procedure DataBitCBoxChange(Sender: TObject); procedure DechiffrierenMenuEClick(Sender: TObject); procedure TextChange(Sender: TObject); procedure BildanzeigenMenuEClick(Sender: TObject); procedure SpeicherBmp(Sender: TObject); procedure SpeicherTxt(Sender: TObject); procedure ClearTextBtnClick(Sender: TObject); private { Private-Deklarationen } steghide : TStegHide; bmp_geladen, bmp_geaendert, txt_geladen : boolean; bmp_DateiName : string; txt_DateiName : string;
function EndsWith (text,teststring : string):boolean; procedure MaskeAktualisieren; function TextLaenge : integer;
public { Public-Deklarationen } end;
var MainFrm: TMainFrm;
implementation (* ==================================================================== *) {$R *.DFM} ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// // Private ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// function TMainFrm.EndsWith; (* -------------------------------------------------------------------- *) var textlength, testlength : integer; vergleichstring : string; begin Result := false; testlength := length(teststring); textlength := length (text); if textlength > testlength then begin vergleichstring := copy (text,(textlength+1)-testlength,testlength); if vergleichstring = teststring then result := true end; end;
procedure TMainFrm.MaskeAktualisieren; (* -------------------------------------------------------------------- *) begin if BildanzeigenMenuE.Checked then Image.Picture.Bitmap := steghide.getBmp; Invalidate; end; ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// // Form-routines ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// procedure TMainFrm.LadeBmp; begin if BmpOpenDialog.Execute then begin bmp_DateiName:= BmpOpenDialog.FileName;
if not steghide.LoadBmp(bmp_DateiName) then begin ShowMessage('Bitmap ' + bmp_Dateiname + ' konnte nicht geladen werden!'); exit; end;
MainFrm.Caption := 'PGH - ' + bmp_DateiName; MaxTextLbl2.Caption := IntToStr(steghide.GetMaxTextLength); bmp_geladen := true;
MaskeAktualisieren; end; end;
procedure TMainFrm.LadeTextDatei; (* -------------------------------------------------------------------- *) var datei : Textfile; tmpstring : string; begin if txt_DateiName <> '' then TxtOpenDialog.FileName := txt_DateiName; if TxtOpenDialog.Execute then begin txt_DateiName := TxtOpenDialog.FileName; assignfile(datei, txt_DateiName); {$i-} Reset(datei); {$i+} if IOResult <> 0 then exit; if GeheimTextMemo.Lines.Count > 0 then if MessageDlg('Soll der bestehende Text gelöscht werden?', mtConfirmation, [mbYes, mbNo], 0)= mrYes then GeheimTextMemo.Clear; while not EOF(datei) do begin readln(datei, tmpstring); GeheimTextMemo.Lines.Append(tmpstring); end; closefile(datei); txt_geladen := true; end; end;
procedure TMainFrm.EndMenuEClick(Sender: TObject); (* -------------------------------------------------------------------- *) begin Close; end;
procedure TMainFrm.AboutMenuEClick(Sender: TObject); (* -------------------------------------------------------------------- *) begin AboutBox.Show; end;
procedure TMainFrm.FormCreate(Sender: TObject); (* -------------------------------------------------------------------- *) begin StegHide := TStegHide.Create; StegHide.SetText(GeheimTextMemo.Lines); //LoadConfig; //DatenAktualisieren; //StegHide.Init;
bmp_DateiName := ''; txt_DateiName := ''; bmp_geladen := false; bmp_geaendert := false; txt_geladen := false; DataBitCBox.ItemIndex := 0; TextLengthLbl2.Caption := IntToStr(Textlaenge); end;
procedure TMainFrm.FormClose(Sender: TObject; var Action: TCloseAction); (* -------------------------------------------------------------------- *) begin if bmp_geaendert then case MessageDlg('Soll das geänderte Bild gespeichert werden?', mtConfirmation, [mbYes, mbNo, mbCancel], 0) of id_Yes: SpeicherBmp(Self); id_Cancel: begin Action := caNone; exit; end;
end; StegHide.Free; end;
procedure TMainFrm.ChiffrierentMenuEClick(Sender: TObject); (* -------------------------------------------------------------------- *) begin if (GeheimTextMemo.Lines.Count > 0) and bmp_geladen then begin steghide.SetText(GeheimTextMemo.Lines); if not steghide.Chiffrieren then ShowMessage('Text wurde nicht korrekt chiffriert!'); bmp_geaendert := true;
MaskeAktualisieren; end else ShowMessage('Bitte Bitmap laden und einen Text eingeben!'); end;
procedure TMainFrm.DataBitCBoxChange(Sender: TObject); (* -------------------------------------------------------------------- *) begin steghide.SetDatenBit(DataBitCBox.ItemIndex); end;
procedure TMainFrm.DechiffrierenMenuEClick(Sender: TObject); (* -------------------------------------------------------------------- *) begin if bmp_geladen then begin GeheimTextMemo.Clear; steghide.Dechiffrieren; end else ShowMessage('Bitte Bitmap zum dechiffrieren laden!'); end;
procedure TMainFrm.TextChange(Sender: TObject); (* -------------------------------------------------------------------- *) begin TextLengthLbl2.Caption := IntToStr(Textlaenge); end;
procedure TMainFrm.BildanzeigenMenuEClick(Sender: TObject); (* -------------------------------------------------------------------- *) begin if BildanzeigenMenuE.Checked then begin BildanzeigenMenuE.Checked := false; Image.Hide; end else begin BildanzeigenMenuE.Checked := true; Image.Visible := true; MaskeAktualisieren; end; end;
procedure TMainFrm.SpeicherBmp(Sender: TObject); (* -------------------------------------------------------------------- *) var tempbmp : TBitmap; begin if not bmp_geladen then begin ShowMessage('Bitte ein Bitmap laden!'); exit; end; if BmpSaveDialog.Execute then begin if fileexists(BmpSaveDialog.FileName) then if MessageDlg('Soll die Datei '+ BmpSaveDialog.FileName + ' wirklich überschrieben werden?', mtConfirmation, [mbYes, mbNo], 0)= mrNo then SpeicherBmp(Self);
if not endswith(BmpSaveDialog.FileName, '.bmp') then BmpSaveDialog.FileName:= BmpSaveDialog.FileName + '.bmp';
steghide.WriteBmp(BmpSaveDialog.FileName); bmp_geaendert := false; end; end;
procedure TMainFrm.SpeicherTxt(Sender: TObject); (* -------------------------------------------------------------------- *) var datei : textfile; i : integer; begin if GeheimTextMemo.Lines.Count = 0 then begin ShowMessage('Bitte einen Text eingeben!'); exit; end; if TxtSaveDialog.Execute then begin if fileexists(TxtSaveDialog.FileName) then if MessageDlg('Soll die Datei '+ TxtSaveDialog.FileName + ' wirklich überschrieben werden?', mtConfirmation, [mbYes, mbNo], 0)= mrNo then SpeicherTxt(Self);
if not endswith(TxtSaveDialog.FileName, '.txt') then TxtSaveDialog.FileName:= TxtSaveDialog.FileName + '.txt';
AssignFile(datei, TxtSaveDialog.FileName); {$i-} Rewrite(datei); {$i+} if IOResult <> 0 then begin ShowMessage('Text nicht gespeichert!'); exit; end; for i:= 0 to GeheimTextMemo.Lines.Count-1 do writeln(datei, GeheimTextMemo.Lines[i]); closefile(datei); end; end;
function TMainFrm.TextLaenge; (* -------------------------------------------------------------------- *) var i : integer; begin Result := 0; for i := 0 to GeheimTextMemo.Lines.Count-1 do inc(Result,length(GeheimTextMemo.Lines[i])); end;
procedure TMainFrm.ClearTextBtnClick(Sender: TObject); (* -------------------------------------------------------------------- *) begin if MessageDlg('Soll der Text wirklich gelöscht werden?', mtConfirmation, [mbYes, mbNo], 0)= mrYes then GeheimTextMemo.Clear; end;
end.
unit uStegHide; ///////////////////////////////////////////////////////////////////////// // Klasse zum Erzeugen eines steganographischen Bildes // Programmierer: Norman Niemer // Datum: 30.05.00 ///////////////////////////////////////////////////////////////////////// interface
uses graphics {TBitmap}, sysutils {PByteArray}, classes {TStrings};
const BitArr: array[0..7] of byte = (1, 2, 4 , 8 , 16, 32, 64, 128); EndOfText = 30; EndOfLine = 29;
type ////////////////////// // TStegHide ////////////////////// TStegHide = class
constructor Create; destructor Destroy;
private bmp:TBitmap; Geheimtext : TStrings; bmp_geladen : boolean; // gibt an, ob ein bmp geladen ist datenbit : byte; // gibt das Bit an, wo die Daten versteckt werden
function BitStatus(SetWord, BitNum : Word) : Boolean; // true, wenn Bit gesetzt procedure ToggleBit( BitNum : byte; var Setbyte : byte); // tauscht die einzelnen Bits
public function Chiffrieren : boolean; function Dechiffrieren : boolean; function GetBmp : TBitmap; function GetMaxTextLength : integer; // gibt Maximalanzahl der vesteckbaren Zeichen zurück function GetText : TStrings; function LoadBmp( dn : string) : boolean; procedure SetDatenBit( dbit : byte ); procedure SetBitmap( tmpbmp : TBitmap ); procedure SetText( txt : TStrings ); function WriteBmp( dn : string) : boolean; end; // TStegHide ///////////////////////////////////////////////////////////////////////// // function chiffrieren // Aufgabe: versteckt die information im bmp // vorher: bmp ist geladen // nachher: information ist versteckt // // function dechiffrieren // Aufgabe: findet versteckte information // vorher: bmp ist geladen // nachher: information // // function Getmaxtextlenght // Aufgabe: gibt die maximale Textlänge, die in dem // geladenen Bmp versteckt werden kann zurück // vorher: bmp ist geladen // Nachher: // // funcion loadbmp // Aufgabe: lädt das bmp // vorher: bmp_geladen := false // nachher: bmp_geladen := true // // procedure SetDatenBit // Aufgabe: setzt das Bit, auf welchen die Informationen vesteckt werden // // function writeBmp // Aufgabe: speichert das veränderte bmp // vorher: bmp ist nicht gespeichert // nachher: bmp ist gespeichert ///////////////////////////////////////////////////////////////////////// implementation ////////////////////////////////////////////////// // General ////////////////////////////////////////////////// constructor TStegHide.Create; begin inherited Create; bmp := TBitmap.Create; Geheimtext := TStrings.Create; bmp_geladen := false; datenbit := 0; end;
destructor TStegHide.Destroy; begin bmp.Free; end; /////////////////////////////////////////////////// // Private /////////////////////////////////////////////////// function TStegHide.BitStatus(SetWord, BitNum : Word) : Boolean; begin if (SetWord and BitNum) = BitNum then Result := true else Result := false; end;
procedure TStegHide.ToggleBit; begin Setbyte := Setbyte Xor BitNum; end; /////////////////////////////////////////////////// // Public /////////////////////////////////////////////////// function TStegHide.Chiffrieren; var x, y, for_char, for_string, for_text : integer; ascii : byte; pixels : PByteArray; last_line : boolean;
procedure GetNewLine; begin pixels := bmp.ScanLine[x]; inc(x); if x >= bmp.height then last_line := true; y := 0; end;
begin Result := false; if not bmp_geladen then exit;
x := 0; last_line := false; GetNewLine;
if Geheimtext.Count = 0 then exit;
for for_text := 0 to geheimtext.Count-1 do begin for for_string := 1 to length(Geheimtext[for_text]) do begin ascii := ord(geheimtext[for_text][for_string]); for for_char := 0 to 7 do begin if not ((BitStatus(ascii, BitArr[for_char])) = (BitStatus(pixels[y], BitArr[datenbit]))) then ToggleBit(BitArr[datenbit], pixels[y]);
inc(y); if y >= bmp.width then if last_line then exit else GetNewLine; end; end;
ascii := EndOfLine; // signalisiert das Ende einer Zeile for for_char := 0 to 7 do begin if not ((BitStatus(ascii, BitArr[for_char])) = (BitStatus(pixels[y], BitArr[datenbit]))) then ToggleBit(BitArr[datenbit], pixels[y]); inc(y); if y >= bmp.width then if last_line then exit else GetNewLine; end; end;
ascii := EndOfText; // signalisiert das Ende des Textes for for_char := 0 to 7 do begin if not ((BitStatus(ascii, BitArr[for_char])) = (BitStatus(pixels[y], BitArr[datenbit]))) then ToggleBit(BitArr[datenbit], pixels[y]); inc(y); if y >= bmp.width then if last_line then exit else GetNewLine; end;
Result := true; end;
function TStegHide.Dechiffrieren; var geheimzeile : string; ascii : byte; for_char, x, y : integer; pixels : PByteArray; i : integer; //debug begin for_char := 0; ascii := 0; Geheimtext.Clear; Result := false; i := 0;
for x:= 0 to bmp.Height-1 do begin pixels := bmp.ScanLine[x]; for y:= 0 to bmp.Width-1 do begin if not ((BitStatus(ascii, BitArr[for_char])) = (BitStatus(pixels[y], BitArr[datenbit]))) then ToggleBit(BitArr[for_char], ascii);
inc(for_char); if for_char = 8 then begin if ascii = EndOfText then begin Result := true; exit; end; // Ende des Textes wurde erreicht if ascii = EndOfLine // Ende einer Zeile then begin Geheimtext.Append(geheimzeile); geheimzeile := ''; end else geheimzeile := geheimzeile + Chr(ascii); for_char := 0; ascii := 0; end; end; end; end;
function TStegHide.GetBmp; begin Result := bmp; end;
function TStegHide.GetMaxTextLength; begin Result := ( bmp.width * bmp.height ) div 8; end;
function TStegHide.GetText; begin Result := TStrings.Create; Result := Geheimtext; end;
function TStegHide.LoadBmp; begin Result := false; try bmp.LoadFromFile(dn); except exit; end; Result := true; bmp_geladen := true; end;
procedure TStegHide.SetBitmap; begin bmp := tmpbmp; if not bmp_geladen then bmp_geladen := true; end;
procedure TStegHide.SetDatenBit; begin datenbit := dbit; end;
procedure TStegHide.SetText; begin Geheimtext := txt; end;
function TStegHide.WriteBmp; begin Result := false; try bmp.SaveToFile(dn); except exit; end; Result := true; end;
end.