Registriert seit: 16. Jul 2003
170 Beiträge
Delphi 6 Enterprise
|
Re: Dateien verschlüsseln - aber wie?
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!
|