Since the size of the code isn't excessive, messages tend to disappear quickly from attachments and I take this matter quite seriously, I post the code here too.
Please note that the code is neither pretty nor optimized. But it works, and in this case that's fatal.
---
Here is a small demonstration of how to perform a trivial known plain
text differential attack against EZCrypt. You need approximately 8 bytes
of consequtive known plain text to narrow down the number of possible
keys to below 100. It will just take a couple of seconds to run this
attack. Increasing the amount of known plain text will further reduce
the number of possible keys with practically no time penalty.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, StdCtrls;
type
EightByte = array [0..7] of Byte;
ThreeWord = array [0..2] of Word;
Guess = packed record
L: Byte;
J: Byte;
K: Word;
R: Word;
end;
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
PT: EightByte; // Plain text
KS: EightByte; // Key stream, i.e. CT xor PT
RealKey: ThreeWord;
Guesses: array of Guess;
GuessCount: Integer;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
W: Word;
I: Integer;
begin
RealKey[0] := Random(65535) + 1;
RealKey[1] := Random(65535) + 1;
RealKey[2] := Random(65535) + 1;
W := RealKey[2];
for I := 0 to 7 do begin
PT[I] := Random(256);
KS[I] := W shr 8;
W := Byte(PT[I] + W)*RealKey[0] + RealKey[1];
end;
SetLength(Guesses,0);
GuessCount := 0;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Randomize;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
I, J, K, L: Integer;
P1, P2, W, R: Word;
D1, D: Byte;
begin
D1 := Byte(KS[2] - KS[1]);
for I := -256 to 255 do begin
for K := 1 to 65535 do begin
W := I*K;
D := W shr 8;
if (D = D1) or (D = Byte(D1-1)) or (D = Byte(D1+1)) then begin
for L := 0 to 255 do begin
J := Byte(I - PT[1] + L + PT[0]);
P1 := Byte(L + PT[0])*K;
P2 := Byte(J + PT[1])*K;
R := Word(Word(KS[1] shl 8) + J - P1);
W := Word(P2 + R);
if (W shr 8) = KS[2] then begin
W := Byte(W + PT[2])*K + R;
if (W shr 8) = KS[3] then begin
W := Byte(W + PT[3])*K + R;
if (W shr 8) = KS[4] then begin
W := Byte(W + PT[4])*K + R;
if (W shr 8) = KS[5] then begin
W := Byte(W + PT[5])*K + R;
if (W shr 8) = KS[6] then begin
W := Byte(W + PT[6])*K + R;
if (W shr 8) = KS[7] then begin
if Length(Guesses) = GuessCount then
SetLength(Guesses,GuessCount + 256);
Guesses[GuessCount].J := J;
Guesses[GuessCount].L := L;
Guesses[GuessCount].K := K;
Guesses[GuessCount].R := R;
Inc(GuessCount);
end;
end;
end;
end;
end;
end;
end;
end;
end;
end;
for I := 0 to GuessCount - 1 do
if (Guesses[I].K = RealKey[0]) and
(Guesses[I].R = RealKey[1]) then
Memo1.Lines.Add('Hit');
Memo1.Lines.Add(IntToStr(GuessCount));
end;
end.
--
Henrick Hellström,
StreamSec http://www.streamsec.com
Need to security enhance your Delphi application? Don't settle for anything less than StrSecII:
http://www.streamsec.com/download_strsec50.asp
I like the EZCrypt unit. Do you have an example of how to use it in a
program for us newbies?
Thanks,
Jim (jmiller55@hotmail.com)
On Sat, 27 Apr 2002 10:13:47 GMT, Ben Hochstrasser
<tictactux123^H^H^H@surfeu.ch> wrote:
>Here's a simple yet effective encryption function (seen at borlands' eons ago, turned into a unit and
>made faster...)
>
>unit EZCrypt;
>
>{modeled by Ben Hochstrasser(bhoc@surfeu.ch) after some code snippet from borland)
>
>interface
>
>uses Windows, Classes;
>
>type
> TWordTriple = Array[0..2] of Word;
>
>function FileEncrypt(InFile, OutFile: String; Key: TWordTriple): boolean;
>function FileDecrypt(InFile, OutFile: String; Key: TWordTriple): boolean;
>function TextEncrypt(const s: string; Key: TWordTriple): string;
>function TextDecrypt(const s: string; Key: TWordTriple): string;
>function MemoryEncrypt(Src: Pointer; SrcSize: Cardinal; Target: Pointer; TargetSize: Cardinal; Key: TWordTriple): boolean;
>function MemoryDecrypt(Src: Pointer; SrcSize: Cardinal; Target: Pointer; TargetSize: Cardinal; Key: TWordTriple): boolean;
>
>implementation
>
>function MemoryEncrypt(Src: Pointer; SrcSize: Cardinal; Target: Pointer; TargetSize: Cardinal; Key: TWordTriple): boolean;
>var
> pIn, pOut: ^byte;
> i : Cardinal;
>begin
> if SrcSize = TargetSize then
> begin
> pIn := Src;
> pOut := Target;
> for i := 1 to SrcSize do
> begin
> pOut^ := pIn^ xor (Key[2] shr 8);
> Key[2] := Byte(pIn^ + Key[2]) * Key[0] + Key[1];
> inc(pIn);
> inc(pOut);
> end;
> Result := True;
> end else
> Result := False;
>end;
>
>function MemoryDecrypt(Src: Pointer; SrcSize: Cardinal; Target: Pointer; TargetSize: Cardinal; Key: TWordTriple): boolean;
>var
> pIn, pOut: ^byte;
> i : Cardinal;
>begin
> if SrcSize = TargetSize then
> begin
> pIn := Src;
> pOut := Target;
> for i := 1 to SrcSize do
> begin
> pOut^ := pIn^ xor (Key[2] shr 8);
> Key[2] := byte(pOut^ + Key[2]) * Key[0] + Key[1];
> inc(pIn);
> inc(pOut);
> end;
> Result := True;
> end else
> Result := False;
>end;
>
>function TextCrypt(const s: string; Key: TWordTriple; Encrypt: Boolean): string;
>var
> bOK: Boolean;
>begin
> SetLength(Result, Length(s));
> if Encrypt then
> bOK := MemoryEncrypt(PChar(s), Length(s), PChar(Result), Length(Result), Key)
> else
> bOK := MemoryDecrypt(PChar(s), Length(s), PChar(Result), Length(Result), Key);
> if not bOK then Result := '';
>end;
>
>function FileCrypt(InFile, OutFile: String; Key: TWordTriple; Encrypt: Boolean): boolean;
>var
> MIn, MOut: TMemoryStream;
>begin
> MIn := TMemoryStream.Create;
> MOut := TMemoryStream.Create;
> Try
> MIn.LoadFromFile(InFile);
> MOut.SetSize(MIn.Size);
> if Encrypt then
> Result := MemoryEncrypt(MIn.Memory, MIn.Size, MOut.Memory, MOut.Size, Key)
> else
> Result := MemoryDecrypt(MIn.Memory, MIn.Size, MOut.Memory, MOut.Size, Key);
> MOut.SaveToFile(OutFile);
> finally
> MOut.Free;
> MIn.Free;
> end;
>end;
>
>function TextEncrypt(const s: string; Key: TWordTriple): string;
>begin
> Result := TextCrypt(s, Key, True);
>end;
>
>function TextDecrypt(const s: string; Key: TWordTriple): string;
>begin
> Result := TextCrypt(s, Key, False);
>end;
>
>function FileEncrypt(InFile, OutFile: String; Key: TWordTriple): boolean;
>begin
> Result := FileCrypt(InFile, OutFile, Key, True);
>end;
>
>function FileDecrypt(InFile, OutFile: String; Key: TWordTriple): boolean;
>begin
> Result := FileCrypt(InFile, OutFile, Key, False);
>end;
>
>end.
>
>
>