@Hagen
erst mal besten Dank für die schnelle und informative Antwort.
1. Byte- oder BlockChiper ...
Definitionirrtum von mir, ich dachte ByteChiper sind die,
die mit Buffer=1Byte arbeiten. Hier geht’s aber mehr um
den Ciphermode.
2. Delphirandom
diesbezüglich brauche ich mir keine weiteren Sorgen (unsicher und so) machen?
Ich habe versucht das "Besprochene" Testweise (mit
DEC) nachzubauen.
Bin dabei auf Folgendes gestoßen, wenn man den CBC-Mode anwendet,
hat man das Problem, dass der verschlüsselt gespeicherter Sessionkey
falsch entschlüsselt wird. Lieg daran, das in dem Mode die letzten
4 Bytes (Sessionkey) anderes behandelt werden, weil 20 mod 8 <> 0 ist
(ich kanns leider nicht besser erklären).
Ich konnte mir natürlich helfen, in dem ich beim Sessionkey-Entschlüsseln einfach
4 bytes mehr mitgenommen habe. Du hast bestimmt besseren Vorschlag
Im CFB-Mode tritt das Problem natürlich nicht auf, da Byte für Byte entschlüsselt wird.
Ich dachte nur, dass der CBC sicherer + schneller wäre, oder?
Den Test-Code lege ich bei, vielleicht (wenn’s nicht allzu viel Arbeit macht) "fliegst Du mal drüber"?
Delphi-Quellcode:
var
// "Virtuelle Datei" Aufbau in Bytes:
// 0-19 : Salt
// 20-39: SKey
// 40-XX: Message
g_File: Pointer;
g_FileSize: Integer;
procedure TForm1.EncodeClick(Sender: TObject);
var
hash: THash_SHA1;
fish: TCipher_Blowfish;
salt: array[0..19] of Byte;
temp: Pointer;
begin
//Zufallsdaten erzeugen
RndXORBuffer(RndTimeSeed, salt, sizeof(salt));
//Sessionskey erzeugen
hash:= THash_SHA1.Create(nil);
hash.Init;
hash.Calc(salt, sizeof(salt));
hash.Calc(PChar('Who is John Galt?')^, 17);
hash.Done;
//Temp. Speicher fur SKey + Message reservieren
GetMem(temp, hash.DigestKeySize + Length(Memo1.Text) + 1);
//SKey erstmal nach temp kopieren, soll ja mit Message in einem Rutsch verschlüsselt werden
Move(hash.DigestKey^, temp^, hash.DigestKeySize);
//den Text der Nachricht hollen
SendMessage(Memo1.Handle, WM_GETTEXT, Length(Memo1.Text) + 1, LongInt(PChar(temp) + hash.DigestKeySize));
//Speicher für die "virtuelle Datei", hierdrüber soll der Test-Austausch erfolgen
g_FileSize:= sizeof(salt) + hash.DigestKeySize + Length(Memo1.Text);
GetMem(g_File, g_FileSize + 1);
//Salt unverschlüsselt in die "Datei" schreiben
Move(salt, g_File^, sizeof(salt));
//den Fish erstellen und initialzieren
fish:= TCipher_Blowfish.Create('', nil);
fish.Mode:= cmCBC;
fish.Init(hash.DigestKey^, hash.DigestKeySize, nil);
//Datei (ohne salt) verschlüsseln
fish.EncodeBuffer(temp^, PChar(PChar(g_File) + 20)^, g_FileSize - sizeof(salt));
//Spasseshalber den verschl. Text ausgeben
Memo2.Text:= StrToFormat(pchar(g_File), g_FileSize, fmtHEX);
//aufräumen sollte man auch nicht vergessen
hash.Free;
fish.Free;
freemem(temp);
end;
procedure TForm1.DecodeClick(Sender: TObject);
var
hash: THash_SHA1;
fish: TCipher_Blowfish;
temp: Pointer;
key2: array[0..19+4] of Byte;//4 Byte mehr wegen CBC
begin
//Sessionskey erzeugen
hash:= THash_SHA1.Create(nil);
hash.Init;
hash.Calc(g_File^, 20); //den Salt-Wert nicht vergessen
hash.Calc(PChar('Who is John Galt?')^, 17);
hash.Done;
//Chiper erstellen und initialzieren
fish:= TCipher_Blowfish.Create('', nil);
fish.Mode:= cmCBC;
fish.Init(hash.DigestKey^, hash.DigestKeySize, nil);
//verschl. SKey decodieren
fish.DecodeBuffer(PChar(g_File)[20], key2, 20+4);
if not CompareMem(hash.DigestKey, @key2, 20) then
begin
ShowMessage('Invalid Password'#13#10 +
'SKey1: ' + StrToFormat(PChar(hash.DigestKey), 20, fmtHEX) + #13#10 +
'SKey2: ' + StrToFormat(PChar(@key2), 20, fmtHEX));
end
else begin
GetMem(temp, g_FileSize - 20 + 1);
fish.DecodeBuffer(pchar(g_File)[20], temp^, g_FileSize - 20);
//den entschl. Text (ohne salt) ausgeben
SendMessage(Memo3.Handle, WM_SETTEXT, 0, LongInt(@PChar(temp)[20]));
FreeMem(temp);
end;
hash.Free;
fish.Free;
end;
Gruß Andreas
PS: Ich hoffe, das ich mit meinem miserabelschlechten Deutsch die Ohren der Forumteilnehmer nicht
beleidigt habe.