Einzelnen Beitrag anzeigen

daniel-volk

Registriert seit: 16. Jul 2003
170 Beiträge
 
Delphi 6 Enterprise
 
#30

Re: Dateien verschlüsseln - aber wie?

  Alt 3. Okt 2003, 01:12
Hi,

ich bin's mal wieder:
Ich hab mein Prog jetzt so weit, dass es Texte verschlüsselt und in gewisser Weise auch Dateien.
Aber bei den Dateien stehe ich vor einem Problem:
Ich schaffe es einfach nicht den Hashwert der Originaldatei (ein 28-stelliger String) so zu speichern, dass ich ihn hinterher auch wieder lesen kann. Und vor dem Entschlüsseln der Datei muss ich den String ja sicherlich auch irgendwie wieder aus dem Header entfernen.

Mein Code sieht bis jetzt folgendermaßen aus:
Delphi-Quellcode:
const
  DefCipherClass: TCipherClass = TCipher_Rijndael; //mögliche siehe Cipher.pas und Cipher1.pas
  DefHashClass: THashClass = THash_SHA1; //mögliche siehe Hash.pas
  DefStringFormat: Integer = fmtMIME64; //mögliche siehe DECUtil.pas
  HashLength = 28; // Länge des Hash-Wertes als String geschrieben
  CipherMode = cmCTS; // Cipher-Mode: cmCTS, cmCBC, cmCFB, cmOFB, cmECB
  ErrorMessageText = 'Fehler: Es wurde entweder ein falsches Kennwort eingegeben oder der Ciphertext wurde manipuliert.'; // Nachricht, die bei falschem Passwort etc angezeigt wird
  ErrorMessageFile = 'Fehler: Es wurde entweder ein falsches Kennwort eingegeben oder die Quelldatei wurde manupuliert.';
  // Modi zur Definition der Dateioperationen
  mdNormal = 0;
  mdClear = 1;
  mdWipe = 2;
  // Modus: mdNormal: Quelldatei bleibt erhalten, Temp (selbst verschlüsselt) wird normal gelöscht
  // mdClear: Quelldatei wird normal gelöscht, ansonsten s.o.
  // mdWipe: Quell- und Tempdatei werden gewiped

  NoSourceMessage = 'Die Quelldatei konnte nicht gefunden werden';
  DestExistsMessage = 'Die Ausgabedatei existiert bereits. Soll Sie überschrieben werden?';
  DestExistsCaption = 'Ausgabedatei existiert bereits';
  ErrorMessage = 'Fehler: Eine der durchzuführenden Operationen konnte eventuell nicht ordnungsgemäß ausgeführt werden.';

implementation

{$R *.dfm}

function TFrmCipher.ReadHeader(Filename: string): string;
var
  Header: string;
  FileStream: TFileStream;
begin
  FileStream := TFileStream.Create(Filename, fmOpenRead);
  if not Assigned(FileStream) then
  begin
    RaiseLastOSError();
    exit;
  end;
  try
    FileStream.ReadBuffer(Header, Hashlength);
    result := Header;
  finally
    FreeAndNil(FileStream);
  end;
end;

function TFrmCipher.DecodeFile(Input, Output, Passwd : string; Modus : word):boolean;
// mdNormal = 0
// mdClear = 1
// mdWipe = 2
var
  DateiHash : string;
  OldHash : string;
begin
  If FileExists(Input)
  then begin
  // Abbruchkriterium, falls DestFile Existiert
  If FileExists(Output) then if Application.MessageBox(DestExistsMessage,DestExistsCaption,MB_YESNO)=7 then exit;
  // Original-Hash-Wert aus Dateiheader auslesen
  OldHash := ReadHeader(Input);
  // Datei verschlüsseln
  with DefCipherClass.Create('',nil)
  do begin
       try
         // Cipher einstellen
         Mode := CipherMode;
         HashClass := DefHashClass;
         InitKey(Passwd,nil);
         CodeFile(Input,Output,paDecode);
         // Hash-Wert der Originaldatei berechnen
         with DefHashClass.Create(nil)
         do begin
              try
                DateiHash := CalcFile(Output,nil,DefStringFormat);
              finally
                Free;
              end;
            end;
       finally
         Free;
       end;
    If OldHash <> DateiHash
    then begin
           ShowMessage(ErrorMessageFile);
           Exit;
         end;
    If FileExists(Output)
    then begin
           Case Modus of
           1 : DeleteFile(Input);
           2 : begin
                 with DefCipherClass.Create('',nil)
                 do begin
                      try
                        InitKey('',nil);
                        CodeFile(Input, Input, paWipe);
                        DeleteFile(Input);
                      finally
                        Free;
                      end;
                    end;
               end;
           end;
         end
         else ShowMessage(ErrorMessage);
     end;
    end
    else ShowMessage(NoSourceMessage);
    Result := FileExists(Output);
end;

function TFrmCipher.AddHeader(Header: string; Filename: String; Modus : integer): Boolean;
var
  SourceFile, DestFile: TFileStream;
const
  extension = '.tmp';
begin
  result := FALSE;
  SourceFile := TFileStream.Create(Filename, fmOpenRead);
  if not Assigned(SourceFile) then
  begin
    exit;
  end;
  try
    DestFile := TFileStream.Create(Filename+Extension, fmCreate);
    if not Assigned(DestFile) then
    begin
      exit;
    end;
    try
      { Header in die Zieldatei schreiben }
      DestFile.WriteBuffer(Header, sizeof(Header));
      { Quelldatei dahinter kopieren / anhängen }
      DestFile.CopyFrom(SourceFile, SourceFile.Size);
      result := TRUE;
    finally
      FreeAndNil(DestFile);
    end;
  finally
    FreeAndNil(SourceFile);
  end;
  // Löschen der temporären Datei
  Case Modus of
  0 or 1: DeleteFile(Filename);
  2:begin
      with DefCipherClass.Create('',nil)
      do begin
           try
             InitKey('',nil);
             CodeFile(Filename,Filename,paWipe);
             DeleteFile(Filename);
           finally
             Free;
           end;
         end;
    end;
  end;
  if not RenameFile(Filename+Extension, Filename) then
  begin
    result := FALSE;
  end;
end;

function TFrmCipher.EncodeFile(Input, Output, Passwd : string; Modus : word):boolean;
// mdNormal = 0
// mdClear = 1
// mdWipe = 2
var
  DateiHash : string;
begin
  If FileExists(Input)
  then begin
  // Abbruchkriterium, falls DestFile Existiert
  If FileExists(Output) then if Application.MessageBox(DestExistsMessage,DestExistsCaption,MB_YESNO)=7 then exit;
  // Datei verschlüsseln
  with DefCipherClass.Create('',nil)
  do begin
       try
         Mode := CipherMode;
         HashClass := DefHashClass;
         InitKey(Passwd,nil);
         CodeFile(Input,Output,paEncode);
         // Hash-Wert der Originaldatei berechnen
         with DefHashClass.Create(nil)
         do begin
              try
                DateiHash := CalcFile(Input,nil,DefStringFormat);
              finally
                Free;
              end;
            end;
         // Hash-Wert in Datei-Header schreiben
         AddHeader(DateiHash,Output,Modus);
       finally
         Free;
       end;
    If FileExists(Output)
    then begin
           Case Modus of
           1 : DeleteFile(Input);
           2 : begin
                 with DefCipherClass.Create('',nil)
                 do begin
                      try
                        InitKey('',nil);
                        CodeFile(Input, Input, paWipe);
                        DeleteFile(Input);
                      finally
                        Free;
                      end;
                    end;
               end;
           end;
         end
         else ShowMessage(ErrorMessage);
     end;
    end
    else ShowMessage(NoSourceMessage);
    Result := FileExists(Output);
end;

function TFrmCipher.EncodeText(Input, Passwd : string):string;
begin
  // Hash-Wert des Originaltextes hinzufügen (zur späteren Prüfung)
  with DefHashClass.Create(nil)
  do begin
      try
       Result := CalcString(Input,nil,DefStringFormat);
      finally
       Free;
      end;
  // Text verschlüsseln
  with DefCipherClass.Create('', nil)
  do begin
      try
       Mode := CipherMode; // auch möglich: cmCTS, cmCBC, cmCFB, cmOFB, cmECB
       HashClass := DefHashClass; // erforderlich
       InitKey(Passwd, nil);
       Result := Result + CodeString(Input,paEncode,DefStringFormat);
      finally
       Free;
      end;
     end;
    end;
end;

procedure TFrmCipher.Button1Click(Sender: TObject);// Text verschlüsseln
begin
  // Text verschlüsseln
  Screen.Cursor := crHourGlass;
  Memo2.Text := EncodeText(Memo1.Text,Edit1.Text);
  Screen.Cursor := crDefault;
end;

function TFrmCipher.DecodeText(Input, Passwd : string):string;
var HashStr1, HashStr2 : string;
begin
  // alten Hash-Wert auslesen
  HashStr1 := Copy(Input,1,HashLength);
  delete(Input,1,HashLength);
  //Text entschlüsseln
  with DefCipherClass.Create('', nil)
  do begin
      try
       Mode := CipherMode; // auch möglich: cmCTS, cmCBC, cmCFB, cmOFB, cmECB
       HashClass := DefHashClass; // erforderlich
       SetDefaultCipherClass(DefCipherClass); //nicht zwingend erforderlich, da normalerweise automatisch eingestellt
       InitKey(Passwd, nil);
       Result := CodeString(Input,paDecode,DefStringFormat);
      finally
       Free;
      end;
     end;
  // neuen Hash-Wert berechnen
  with DefHashClass.Create(nil)
  do begin
      try
       HashStr2 := CalcString(Result,nil,DefStringFormat);
      finally
       Free;
      end;
     end;
  // Hash-Werte vergleichen
  If HashStr1 <> HashStr2
  then ShowMessage(ErrorMessageText);
end;

procedure TFrmCipher.Button2Click(Sender: TObject);// Text entschlüsseln
begin
  // Text entschlüsseln
  Screen.Cursor := crHourGlass;
  Memo1.Text := DecodeText(Memo2.Text,Edit1.Text);
  Screen.Cursor := crDefault;
end;

procedure TFrmCipher.Button3Click(Sender: TObject);// Datei verschlüsseln
var
  Modus : word;
begin
  Screen.Cursor := crHourGlass;
  If RadioButton1.Checked then Modus := 0 else
  If RadioButton2.Checked then Modus := 1 else
  If RadioButton3.Checked then Modus := 2 else
  begin
  ShowMessage(ErrorMessage);
  exit;
  end;
  EncodeFile(Edit2.Text,Edit3.Text,Edit1.Text,Modus);
  Screen.Cursor := crDefault;
end;

procedure TFrmCipher.Button4Click(Sender: TObject);// Datei entschlüsseln
var
  Modus : word;
begin
  Screen.Cursor := crHourGlass;
  If RadioButton1.Checked then Modus := 0 else
  If RadioButton2.Checked then Modus := 1 else
  If RadioButton3.Checked then Modus := 2 else
  begin
  ShowMessage(ErrorMessage);
  exit;
  end;
  DecodeFile(Edit2.Text,Edit3.Text,Edit1.Text,Modus);
  Screen.Cursor := crDefault;
end;

end.
Irgendwas muss da doch falsch sein. Ich weiß nur nicht so genau was.

Und noch etwas: Ich habe auf das Auffüllen mit Zufallsdaten verzichtet, weil ich sonst irgendwann an einem Punkt ankomme, an dem ich wahrscheinlich selbst nicht mehr durch den Code durchsteige (was jetzt schon schwierig ist) und ich doch mal denke, dass der Plaintext ansonsten ja auch nicht so known ist, oder? Abgesehen davon hab ich von der Verschlüsselung an sich zu wenig Ahnung um nun sagen zu können, wie sicherheitsrelevant das ist.

THX for your help,
Daniel!
  Mit Zitat antworten Zitat