AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Dateien verschlüsseln - aber wie?

Ein Thema von daniel-volk · begonnen am 27. Sep 2003 · letzter Beitrag vom 14. Mär 2004
Antwort Antwort
Seite 3 von 11     123 45     Letzte »    
daniel-volk

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

Re: Dateien verschlüsseln - aber wie?

  Alt 30. Sep 2003, 21:30
Danke!!!

Das hat mir glaub ich sehr geholfen (und sicherlich auch einigen Anderen).
Das größte Problem war wohl, dass ich keine initialization geschrieben hatte.

Na ja, jetzt wird's schon gehn.

MfG,
Daniel.
  Mit Zitat antworten Zitat
daniel-volk

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

Re: Dateien verschlüsseln - aber wie?

  Alt 1. Okt 2003, 21:26
Hi,

komme inzwischen ganz gut klar.
Hab mir die für mich wichtigen Aspekte aus deinen Posts angesehen und die Units durchgearbeitet.

Anfangs bin ich nur daran verzweifelt, dass ich Rijndael einfach nicht definieren konnte und auch nicht in der Unit fand - bis ich dann feststellte, dass es neben Cipher auch noch Cipher1 gibt!!!

So weit so gut, es gibt ja die Aktionen paEncode (zum Verschlüsseln), paDecode (entschlüsseln) und dann noch paWipe. Über die Funktion des Letzten bin ich mir nicht im Klaren. Wiped das die Quelldatei oder was?

Gibt es eigentlich eine Funktion zum Wipen von Dateien, sodass ich die Option "Quelldatei nach Verschlüsseln wipen" einbauen kann?

Und: Der CipherManager verfügt über ein OnProgress Event. Wie kann ich darauf zugreifen, wenn ich den Manager nicht verwende (was bei mir der Fall ist)?

Danke,
Daniel.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#23

Re: Dateien verschlüsseln - aber wie?

  Alt 2. Okt 2003, 05:32
Eine Frage noch: Das Passwort wird im Header logischerweise nur als Hash-Wert gespeichert oder?

Also:
Code:
////////////////////////////////
Header
  CipherIdentity: Cardinal
  HashIdentity: Cardinal
  PW als Hash: String;
////////////////////////////////
Daten
  verschlüsselte Datei
  ...
  ...
  ...
  ...
  ...
  ...
  ...
////////////////////////////////
Den Header darf man natürlich nicht mit verschlüsseln, also erst die Datei verschlüsseln und dann den Header dazupacken. Beim Entschlüsseln Header auslesen, Passwort überprüfen, Header aus der verschlüsselten Datei entfernen, entschlüsseln.

Hm.

Der Passwort Hash wird ja ein String. Wie schreibt man denn ein Header-Record mit eienm Delphi HugeString, also mit einem String dessen Länge man nicht kennt? Somit ist ja auch die Headergröße nicht bekannt. Oder kann man davon ausgehen, dass ein Hash nicht länger wird als 255 Zeichen?

PS. Ich denke nur mal laut.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#24

Re: Dateien verschlüsseln - aber wie?

  Alt 2. Okt 2003, 09:45
Zitat:
So weit so gut, es gibt ja die Aktionen paEncode (zum Verschlüsseln), paDecode (entschlüsseln) und dann noch paWipe. Über die Funktion des Letzten bin ich mir nicht im Klaren. Wiped das die Quelldatei oder was?
Jetzt dringen wir tiefer in die DEC Klassen ein, und man erkennt viele Sünden die ich heute nicht mehr so designen würde. TCipher/THash und TRandom sind alle von der gleichen Klasse TProtection abgeleitet. Jede Klasse wie TCipher/THash/TRandom implementieren ihre EIGENEN Methoden die natürlich Algorithmen spezifisch sind. D.h. ein TCipher hat die Methoden .En-/DecodeBuffer, .En-/DecodeString() usw. zum Ver- und Entschlüsseln. Ein THash wiederum seine .CalcXYZ usw Methoden. Diese Methoden unterstützen KEINE ProgressCallback.

Aber in TProtection gibt es ebenfalls ähnliche Methoden, die für ALLE von TProtection abgeleiteten Klassen gültig sind, Zb. TProtection .CodeStream(). Man kann also mit einem Cipher/Hash/Random ebenfalls über diese Methoden von TProtection Daten verschlüsseln. Kryptographisch gesehen würde ich aus heutiger Sicht meine damaligen Absichten als naiv bezeichnen, und nicht mehr auf die TProtection Methoden zurückgreifen. Man kann zwar tatsächlich auch mit einer Hash-Funktion eine Verschlüsselung machen, man nennt diese offiziell MDC=Message Digest Cipher, heutzutage würde ich aber grundsätzliche solche Verfahren ablehnen. Nungut, DEC enthält sie und somit muß ich auch darauf eingehen. Nur die Methoden von TProtection enthalten die Möglichkeit eine Progress-Callback zu benutzen. Hier im Forum findest du in der Codelibrary einen TProgressStreamAdapter der diese Progressfunktionalität viel eleganter lösst. Die im DEC enthaltene Callback ist global und nicht threadsafe und funktioniert nur mit den TProtection.CodeXXXX Methoden. Also wiederum einige Nachteile. Um denoch einen Progress zu coden schauste mal in DECUtil.pas rein, dort findest du eine globale Variable "Progress: TProgressEvent". Diese musst du vor der Benutzung von TProtection.CodeXXXX() auf eine eigene Eventmethode setzen und danach wieder auf nil. Genauso gehen auch die Manager Components vor.

Zitat:
Gibt es eigentlich eine Funktion zum Wipen von Dateien, sodass ich die Option "Quelldatei nach Verschlüsseln wipen" einbauen kann?
Jo, eben paWipe Du erzeugt einen TCipher oder TRandom und benutzt dann die Methoden von TProtection mit der Action paWipe statt paEncode.

Zitat:
Und: Der CipherManager verfügt über ein OnProgress Event. Wie kann ich darauf zugreifen, wenn ich den Manager nicht verwende (was bei mir der Fall ist)?
Ähm, oben schon beantwortet.

@Luckie:
Zitat:
Eine Frage noch: Das Passwort wird im Header logischerweise nur als Hash-Wert gespeichert oder?
Es sollte überhaupt nicht mehr gespeichert werden, egal in welcher Form. Ansonsten sind bei bekannter Hashtransformation des Passwortes immer Wörterbuch-Angriffe möglich die mit schlecht gewähltem Passwort sehr efizient sein können.

Also wichtigste Regel: Ein Passwort ist ein Geheimnis das meistens durch den Menschen sehr schlecht und weit unter den Sicherheitsanforderungen ausgewählt wurde. Deshalb gehört dieses Passwort NUR in's Hirn und sollte in keinerlei Form gespeichert werden. Es sei denn, es würde mit einem viel besseren Passwort verschlüsselt oder transformiert.

Zitat:
Den Header darf man natürlich nicht mit verschlüsseln, also erst die Datei verschlüsseln und dann den Header dazupacken. Beim Entschlüsseln Header auslesen, Passwort überprüfen, Header aus der verschlüsselten Datei entfernen, entschlüsseln.
Dies ist korrekt. In meinem obigen Postings wurde das berücksichtigt. JEDE Funktion die mit Stream's arbeitet, sollte immer ausgehend von der aktuellen Stream.Position mit dem Stream arbeiten. So zumindestens arbeitet die VCL und auch DEC. Werden also aus einem Stream 8 Bytes gelesen und erst danach mit Cipher.DecodeStream() gearbeitet, so beginnt der Cipher mit dem 9'ten Byte im Stream zu entschlüsseln. Einzigste Aussnahme beim DEC ist wenn man z.b. Cipher.DecodeStream(Source, Dest, -1); sprich Size = -1 aufruft. Dann wird intern Stream.Position := 0; gesetzt.
Auch solche "Ausnahmen" würde ich heutzutage NICHT mehr so programmieren.

Zitat:
Der Passwort Hash wird ja ein String. Wie schreibt man denn ein Header-Record mit eienm Delphi HugeString, also mit einem String dessen Länge man nicht kennt? Somit ist ja auch die Headergröße nicht bekannt. Oder kann man davon ausgehen, dass ein Hash nicht länger wird als 255 Zeichen?
Ein Hash erzeugt immer einen binären Digest fester Länge. Z.b. SHA1 eben 20 Bytes. Wird dieser Hash konvertiert, durch TStringFormat_xxxx Klassen, dann werden zwar diese 20 Bytes expandiert, aber trotzdem hat der String dann mit dem gleichen Hash immernoch feste Länge.

Ein Header mit variabler Größe sollte nach dem Ident zur Erkennung des Headers eine Größenangabe in Bytes enthalten. Der Ident und die Größenangabe haben dann feste Länge und können nun direkt ausgelesen werden. Somit besteht ein Header variabler Größe im Grunde genommen aus ZWEI Teilen. Einen festen Part am Anfang aus Ident + Größenangabe und einem variablen Teil gleich danach der exakt Header.Size Bytes groß ist.
Generell bevorzuge ich aber Header die immer feste Länge haben, meistens 16,32,48 Bytes. Der Rest der fehlenden Bytes um auf diese Größen zu kommen wird einfach reserviert. Damit sind dann auch Erweiterungen des Headers möglich.

Auf eine Verschlüsselung des Headers sollte verzichtet werden, da sonst "known plaintext attacks" möglich sind. Gleich nach dem Header sollte man die Daten verschlüsselt speichern. ABER, diese Daten sollten mit Cipher.BufSize Bytes Zufallsdaten am Anfang erweitert werden.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#25

Re: Dateien verschlüsseln - aber wie?

  Alt 2. Okt 2003, 09:53
Mann, ich sollte ins Bett gehen, das Passwort speichern war natürlich Quatsch mit Soße. Und damit hat sich auch das Header-Problem gelöst.

Aber was man speichern könnte, wäre ein Hash von der original Datei, um nach dem Entschlüsseln überprüfen zu können, ob sie noch in Ordnung ist.

Was machen eigentlich deine Streams, wenn man mit dem falschen Passwort entschlüsselt?
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#26

Re: Dateien verschlüsseln - aber wie?

  Alt 2. Okt 2003, 10:20
Zitat:
Aber was man speichern könnte, wäre ein Hash von der original Datei, um nach dem Entschlüsseln überprüfen zu können, ob sie noch in Ordnung ist.

Was machen eigentlich deine Streams, wenn man mit dem falschen Passwort entschlüsselt?
Sie werden falsch entschlüsselt und produzieren Datenmüll.
Somit ist es eine gute Idee eine Prüfsumme zu berechnen. Dazu benötigt man aber nicht unbedingt eine separate Hashfunktion, sondern man kann im Ciphermode cmCTS einfach nach dem verschlüsseln der Daten mit Cipher.CalcMAC eine Prüfsumme erzeugen. Die Ciphermodes cmCBC,cmCTS ua. sind Modis die per Feedback Register blockweise die Daten zerlegen und jeden Block separat verschlüsseln. Dabei wird aber über das Feedback Register jeder Block mit dem nachfolgenden Block verknüpft. Somit würde sich ein Bitfehler eines Datenblockes in den nächsten Datenblock fortpflanzen. Nun im cmCBC Modus beträfe so ein Fehler nur den nachfolgenden Block und somit ist cmCBC ungeeignet als C-MAC = Cipher-Message Authentification Code. cmCBC nennt man auch einen "Selbst synchronisierenden Modus", da er eben bei einem Bitfehler nur ZWEI Datenblöcke falsch entschlüsselt, alle nachfolgenden Blöcke sind dan wieder ok. Den cmCTS Mode habe ich aber so konstruiert das ein einzigster Bitfehler am Anfang der Message ALLE nachfolgenden Bits beeinflusst. D.h. der Fehler beeinflusst die ganze Nachricht bis zum Ende und somit auch den letzten Block der Nachricht. Wird damit ein C-MAC berechnet und dieser in die Datei gespeichert, kann bei der Entschlüsselung der neue C-MAC mit dem gespeicherten verglichen werden. Sollten sie ungleich sein, so wurde entweder ein falsches Paswort benutzt oder die Daten wurden manipuliert. Allerdings, dieser Modus ist ein "Alles oder Nichts" Modus.

Alternativ könnte man aber den von mir vorgeschlagenen Zufallsdatenblock dazu benutzten um zu erkennen ob das richtige Passwort eingegeben wurde. Der Dateiaufbau sähe dann so aus: Header + Zufallsdaten + Prüfsumme über Zufallsdaten + Message. Bis auf den Header werden alle Teile wie eine einzigste Nachricht verschlüsselt. Bei Entschlüsseln kann man sofort nach Entschlüsselung der Zufallsdaten + Prüfsumme diese erstmal abtesten. Sollte sie falsch sein ist mit hoher Wahrscheinlichkeit das Passwort falsch.

Ein Angreifer der nun per Brute Force und einer Test-Entschlüsslung arbeitet müsste aber dann auch nur bis zur Prüfsumme entschlüsseln um zu sehen ob sein Testpasswort das richtige ist. Macht man es aber über die C-MAC Methode so muß der Angreifer und auch der Benutzer die Message immer vollständig entschlüsseln um zu erfahren ob alles korrekt ist.

Bei all diesen Überlegungen könnte man mich fragen: "warum hast du nicht gleich ein solches Datenformat und Datenprotokoll in DEC integriert ?", denn der zusätzlich nötige Aufwand um mit DEC korrekt und sicher Daten zu verwalten ist ja immernoch erheblich !

Nun, einfach weil es viel zu viele unterschiedliche Anforderungen und Standarddaten Formate gibt. Man kann es also im Grunde keinem richtig Recht machen. Deshalb ist dies die Aufgabe des Benutzers vom DEC.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#27

Re: Dateien verschlüsseln - aber wie?

  Alt 2. Okt 2003, 10:31
Das war ja auch ein Punkt in der DLL von dem Russen, der hat das Passwort in der verschlüsselten Datei gespeichert.

Ich wollte erstmal den Header so einfach wie möglich halten. Das heißt nur die CipherIndetity speichern und eine Prüfsumme der original Datei.

Wie lange braucht es einen Hash/Prüfsumme von einer 100 MB Datei zu erstellen? Wie schnell sind die Hash Algorithmen im DEC? Und kann man da auch mit deinem ProgressAdapter arbeiten, also mit Streams? Wenn es länger dauert könnte man dann einen Fortschritt anzeigen. Dass das sowieso in Threads ausgelagert wird ist klar.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#28

Re: Dateien verschlüsseln - aber wie?

  Alt 2. Okt 2003, 11:42
Zitat:
Wie lange braucht es einen Hash/Prüfsumme von einer 100 MB Datei zu erstellen?
Hängt davon ab mit welchem Algo. gearbeitet wird. Die DEMO im DEC enthält einen Performancevergleich alle Algos. Mit wenigen Handgriffen haste diese auf deine Testfälle umgeändert. Normalerweise sollte MD4 z.b. zwischen 40 - 340 Mb/sec schnell sein.

Zitat:
Wie schnell sind die Hash Algorithmen im DEC?
Relativ gesehen zu den anderen verfügbaren Algos. sind sie enorm schnell. Ich kenne nur zwei andere Implementationen die schneller sind. Einerseits behauptet Henrick Hellström in seinem StreamSec II das seine Implementationen zum Original DEC schneller sind, andererseits hat ein Russe Namens Anatoly Kaluzhinsky die Implementationen im DEC durch handmade Assembler Routinen verbessert. Dessen Algos. sind die schnellsten die ich kenne. Sie liegen bei mir aber auf "Halde" können aber von Tol's WEB Side downloaded werden, http://www.paco.net/~tol/hash/x86hotk.html

Zitat:
Und kann man da auch mit deinem ProgressAdapter arbeiten, also mit Streams? Wenn es länger dauert könnte man dann einen Fortschritt anzeigen. Dass das sowieso in Threads ausgelagert wird ist klar.
Aber natürlich immer. Man darf dann eben nur die DEC Methoden benutzen die auch mit Streams arbeiten. Zwischen dem Orginal-Dateistream und dem Stream auf dem die DEC Methoden arbeiten wird einfach der TStreamProgressAdapter zwischen geschaltet. Somit laufen alle Zugriffe der DEC Methoden direkt über den TStreamProgressAdapeter und dieser leitet sie weiter an den originalen Stream.
Diese Methodik kann mit JEDEM TStream basierten System benutzt werden, sogar zum Laden von DFM's, Indy Streams usw. usw.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#29

Re: Dateien verschlüsseln - aber wie?

  Alt 2. Okt 2003, 11:48
Zitat:
Ich wollte erstmal den Header so einfach wie möglich halten. Das heißt nur die CipherIndetity speichern und eine Prüfsumme der original Datei.
Vergiss nicht die Hash.Identity mitzuspeichern. Diese ist notwendig um den richtigen Hash-Algo, der für die Konvertierung des Passwortes in den Sessionkey benutzt wird, zu setzen. Mit Cipher.HashClass.Identity kannste darauf zugreifen. Die Methode Identity ist eine Klassenmethode kann also auch mit Klassen verwendet werden, eg. THash_MD4.Identity.

Ich empfehle dir dringendst mit der Expansion der Message per Zufallsbytes zu arbeiten. Dies erhöht nicht nur marginal die Sicherheit, sondern ist ein MUSS um es sicher zu machen.

Normalerweise benutzt man dazu die sogenanten Initialization Vectors = IV's. Diese werden mit Zufallsbytes gefüllt und diese Bytes müssen unverschlüsselt mit gespeichert werden damit man wieder entschlüsseln kann. Solche IV's stellen sicher das man bestimmte effektive Angriffe nicht mehr durchführen kann. Nun, ich persönlich finde diese IV's nicht so gut, da sie eben lesbar gespeichert werden. Besser ist es dann gleich diese IV-Zufallsbytes zur Expansion der Nachricht zu verwenden und sie am Anfang der Nachricht mit zu verschlüsseln. Dies hat die gleichen Auswirkungen wie ein IV, ist aber sicherer da sie verschlüsselt sind. IV's und diese Zufallsbytes Expandierung setzen voraus das mit einem Feedback-Ciphermode gearbeitet wird. D.h. cmECB darf dann nicht benutzt werden.
Diese IV's werden in DEC per default durch die Verschlüsselung von 0 Bytes mit dem Passwort initialisiert. Wenn sie also NICHT explizit benutzt werden, so ist der IV im DEC nichts anderes als die Verschlüsselung von 0 Bytes. Nur mit dem richtigen Passwort wäre also in der Entschlüssung der IV identisch mit dem IV zur Verschlüsselung. Dies hat aber den Nachteil das ein Angreifer der dies weis den IV dazu benutzen kann um nur mit einem Block Entschlüsslung und bekanntem Messageheader eine Brute Force Attacke auf das Passwort machen kann. Wird die Message mit Zufallsdaten expandiert funktioniert dies nicht mehr.

Gruß Hagen
  Mit Zitat antworten Zitat
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
Antwort Antwort
Seite 3 von 11     123 45     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:05 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz