Unit DES.pas
unit DES;
interface
Uses Windows, Classes, SysUtils, Math, Dialogs;
Type
TBitString = Array of Boolean;
PBitString = ^TBitString;
TSplitKeyParts = record
C:TBitString;
D:TBitString;
end;
TSplitKey = Array[0..16]Of TSplitKeyParts;
TConcatKey = Array[0..15]Of TBitString;
TIPKeyParts = record
L:TBitString;
R:TBitString;
end;
TIPKey = Array[0..16]OF TIPKeyParts;
Const
DES_PC1:Array[0..55] Of Byte = (57,49,41,33,25,17,9,
1,58,50,42,34,26,18,
10,2,59,51,43,35,27,
19,11,3,60,52,44,36,
63,55,47,39,31,23,15,
7,62,54,46,38,30,22,
14,6,61,53,45,37,29,
21,13,5,28,20,12,4);
DES_PC2:Array[0..47] Of Byte = (14,17,11,24,1,5,
3,28,15,6,21,10,
23,19,12,4,26,8,
16,7,27,20,13,2,
41,52,31,37,47,55,
30,40,51,45,33,48,
44,49,39,56,34,53,
46,42,50,36,29,32);
DES_IP:Array[0..63] Of Byte = (58,50,42,34,26,18,10,2,
60,52,44,36,28,20,12,4,
62,54,46,38,30,22,14,6,
64,56,48,40,32,24,16,8,
57,49,41,33,25,17,9,1,
59,51,43,35,27,19,11,3,
61,53,45,37,29,21,13,5,
63,55,47,39,31,23,15,7);
DES_E:Array[0..47] Of Byte = (32,1,2,3,4,5,
4,5,6,7,8,9,
8,9,10,11,12,13,
12,13,14,15,16,17,
16,17,18,19,20,21,
20,21,22,23,24,25,
24,25,26,27,28,29,
28,29,30,31,32,1);
S_BOXES:Array[0..7,0..3,0..15]Of Byte = (
((14,04,13,01,02,15,11,08,03,10,06,12,05,09,00,07),
(00,15,07,04,14,02,13,01,10,06,12,11,09,05,03,08),
(04,01,14,08,13,06,02,11,15,12,09,07,03,10,05,00),
(15,12,08,02,04,09,01,07,05,11,03,14,10,00,06,13)),
((15,01,08,14,06,11,03,04,09,07,02,13,12,00,05,10),
(03,13,04,07,15,02,08,14,12,00,01,10,06,09,11,05),
(00,14,07,11,10,04,13,01,05,08,12,06,09,03,02,15),
(13,08,10,01,03,15,04,02,11,06,07,12,00,05,14,09)),
((10,00,09,14,06,03,15,05,01,13,12,07,11,04,02,08),
(13,07,00,09,03,04,06,10,02,08,05,14,12,11,15,01),
(13,06,04,09,08,15,03,00,11,01,02,12,05,10,14,07),
(01,10,13,00,06,09,08,07,04,15,14,03,11,05,02,12)),
((07,13,14,03,00,06,09,10,01,02,08,05,11,12,04,15),
(13,08,11,05,06,15,00,03,04,07,02,12,01,10,14,09),
(10,06,09,00,12,11,07,13,15,01,03,14,05,02,08,04),
(13,15,00,06,10,01,13,08,09,04,05,11,12,07,02,14)),
((02,12,04,01,07,10,11,06,08,05,03,15,13,00,14,09),
(14,11,02,12,04,07,13,01,05,00,15,10,03,08,09,06),
(04,02,01,11,10,13,07,08,15,09,12,05,06,03,00,14),
(11,08,12,07,01,14,02,13,06,15,00,09,10,04,05,03)),
((12,01,10,15,09,02,06,08,00,13,03,04,14,07,05,11),
(10,15,04,02,07,12,09,05,06,01,13,14,00,11,03,08),
(09,14,15,05,02,08,12,03,07,00,04,10,01,13,11,06),
(04,03,02,12,09,05,15,10,11,14,01,04,06,00,08,13)),
((04,11,02,14,15,00,08,13,03,12,09,07,05,10,06,01),
(13,00,11,07,04,09,01,10,14,03,05,12,02,15,08,06),
(01,04,11,13,12,03,07,14,10,15,06,08,00,05,09,02),
(06,11,13,08,01,04,10,07,09,05,00,15,14,02,03,12)),
((13,02,08,04,06,15,11,01,10,09,03,14,05,00,12,07),
(01,15,13,08,10,03,07,04,12,05,06,11,00,14,09,02),
(07,11,04,01,09,12,14,02,00,06,10,13,15,03,05,08),
(02,01,14,07,04,10,08,13,15,12,09,00,03,05,06,11))
);
DES_P:Array[0..31] Of Byte = (16,7,20,21,
29,12,28,17,
1,15,23,26,
5,18,31,10,
2,8,24,14,
32,27,3,9,
19,13,30,6,
22,11,4,25);
DES_REVERSE_IP:Array[0..63] Of Byte = (40,8,48,16,56,24,64,32,
39,7,47,15,55,23,63,31,
38,6,46,14,54,22,62,30,
37,5,45,13,53,21,61,29,
36,4,44,12,52,20,60,28,
35,3,43,11,51,19,59,27,
34,2,42,10,50,18,58,26,
33,1,41,9,49,17,57,25);
DES_LSH:Array[0..15] Of Byte = (1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1);
Function BinToInt(S:TBitString):Integer;
Function IntToBin(N:Integer;Precision:Integer=8):TBitString;
Function BinToStr(Bits:TBitString):String;
Function StrToBin(S:String):TBitString;
Function AnsiStrToBin(S:String; Zeroes:Boolean=True):TBitString;
Function BinToAnsiStr(Bits:TBitString):String;
Procedure CopyBits(Var Dest:TBitString; Source:TBitString; NBits:Integer);
Function ConcatBits(Bits:Array Of TBitString):TBitString;
Function DESEncode(S,Key:String):TBitString;
Function DESDecode(S,Key:String):TBitString;
Function GetPermutedKey(Key:TBitString):TBitString;
Function GetPermutedKey2(Key:TBitString):TBitString;
Function GetSplitKey(Key:TBitString):TSplitKey;
Function GetConcatKey(Key:TSplitKey):TConcatKey;
Function GetIPKey(M:TBitString; ConcatKey:TConcatKey):TIPKey;
Function GetF(R,K:TBitString):TBitString;
Function GetSBox(Index:Integer; T:TBitString):TBitString;
Function GetReverseIP(RL:TBitString):TBitString;
Procedure ReverseSubKeys(Var Keys:TConcatKey);
implementation
Function ConcatBits(Bits:Array Of TBitString):TBitString;
Var
I,C:Integer;
Begin
SetLength(Result,0);
For C:=0 To Length(Bits)-1 Do
Begin
SetLength(Result,Length(Result)+Length(Bits[C]));
For I:=0 To Length(Bits[C])-1 Do
Result[Length(Result)-Length(Bits[C])+I]:=Bits[C][I];
End;
End;
Procedure CopyBits(Var Dest:TBitString; Source:TBitString; NBits:Integer);
Var
I:Integer;
Begin
SetLength(Dest,NBits);
For I:=0 To NBits-1 Do
Dest[I]:=Source[I];
End;
Function BinToInt(S: TBitString): Integer;
Var
L,I:Integer;
Begin
Result:=0;
L:=Length(S);
IF L=0 Then
Raise EConvertError.Create('Specified bit string is zero length');
For I:=L-1 DownTo 0 Do
Result:=Result+Ord(S[I])*Trunc(Power(2,L-I-1));
End;
Function IntToBin(N:Integer; Precision:Integer):TBitString;
Var
BitList:TList;
Bit:PBoolean;
Begin
SetLength(Result,0);
BitList:=TList.Create;
While N>0 Do
Begin
New(Bit);
Bit^:=Boolean(N mod 2);
BitList.Insert(0,Bit);
N:=N div 2;
End;
While BitList.Count'1')And(S[I]<>'0') Then
Raise EConvertError.Create(S+' is invalid binary string');
SetLength(Result,I);
Result[I-1]:=Boolean(StrToInt(S[I]));
End;
End;
Function BinToAnsiStr(Bits:TBitString):String;
Var
I:Integer;
B:TBitString;
Begin
Result:='';
SetLength(B,8);
I:=0;
While I<=Length(Bits)-8 Do
Begin
CopyMemory(B,Ptr(Integer(Bits)+I),8);
Result:=Result+Char(BinToInt(B));
Inc(I,8);
End;
End;
Function GetPermutedKey(Key:TBitString):TBitString;
Var
I:Integer;
Begin
SetLength(Result,Length(DES_PC1));
For I:=0 To Length(DES_PC1)-1 Do
Result[I]:=Key[DES_PC1[I]-1];
End;
Function GetPermutedKey2(Key:TBitString):TBitString;
Var
I:Integer;
Begin
SetLength(Result,Length(DES_PC2));
For I:=0 To Length(DES_PC2)-1 Do
Result[I]:=Key[DES_PC2[I]-1];
End;
Function GetSplitKey(Key:TBitString):TSplitKey;
Function LeftShift(Key:TBitString; N:Integer):TBitString;
Var
I,J:Integer;
Temp:TBitString;
Begin
SetLength(Result,28);
SetLength(Temp,28);
For I:=0 To 27 Do
Temp[I]:=Key[I];
For J:=1 To N Do
Begin
For I:=1 To 27 Do
Result[I-1]:=Temp[I];
Result[27]:=Temp[0];
For I:=0 To 27 Do
Temp[I]:=Result[I];
End;
End;
Var
I,J:Integer;
Begin
For J:=1 To 16 Do
Begin
SetLength(Result[J].C,28);
SetLength(Result[J].D,28);
End;
CopyBits(Result[0].C,Key,28);
CopyBits(Result[0].D,TBitString(Integer(Key)+28),28);
For I:=1 To 16 Do
Begin
Result[I].C:=LeftShift(Result[I-1].C,DES_LSH[I-1]);
Result[I].D:=LeftShift(Result[I-1].D,DES_LSH[I-1]);
End;
End;
Function GetConcatKey(Key:TSplitKey):TConcatKey;
Var
I:Integer;
Temp:TBitString;
Begin
For I:=0 To 15 Do
Begin
SetLength(Result[I],56);
Temp:=ConcatBits([Key[I+1].C,Key[I+1].D]);
Result[I]:=GetPermutedKey2(Temp);
End;
End;
Function GetIPKey(M:TBitString; ConcatKey:TConcatKey):TIPKey;
Var
I,J:Integer;
IP, F:TBitString;
Begin
For I:=0 To 16 Do
Begin
SetLength(Result[I].L,32);
SetLength(Result[I].R,32);
End;
SetLength(IP,64);
For I:=0 To Length(DES_IP)-1 Do
IP[I]:=M[DES_IP[I]-1];
For I:=0 To 31 Do
Result[0].L[I]:=IP[I];
For I:=32 To 63 Do
Result[0].R[I-32]:=IP[I];
For I:=1 To 16 Do
Begin
Result[I].L:=Result[I-1].R;
F:=GetF(Result[I-1].R,ConcatKey[I-1]);
For J:=0 To 31 Do
Result[I].R[J]:=Result[I-1].L[J] XOR F[J];
End;
End;
Function GetF(R,K:TBitString):TBitString;
Var
I,J:Integer;
S,E,KE,F,T:TBitString;
Begin
SetLength(E,48);
For I:=0 To 47 Do
E[I]:=R[DES_E[I]-1];
SetLength(KE,48);
For I:=0 To 47 Do
KE[I]:=K[I] XOR E[I];
SetLength(T,6);
SetLength(F,0);
SetLength(S,4);
I:=0;
While I<48 Do
Begin
For J:=0 To 6 Do
T[J]:=KE[J+I];
S:=GetSBox(I div 6,T);
F:=ConcatBits([F,S]);
I:=I+6;
End;
SetLength(Result,32);
For I:=0 To 31 Do
Result[I]:=F[DES_P[I]-1];
End;
Function GetSBox(Index:Integer; T:TBitString):TBitString;
Var
Val,Row,Col:Integer;
Temp:TBitString;
Begin
SetLength(Result,4);
SetLength(Temp,2);
Temp[0]:=T[0];
Temp[1]:=T[5];
Row:=BinToInt(Temp);
SetLength(Temp,4);
CopyBits(Temp,TBitString(@T[1]),4);
Col:=BinToInt(Temp);
Val:=S_BOXES[Index,Row,Col];
SetLength(Result,4);
Result:=IntToBin(Val,4);
End;
Function GetReverseIP(RL:TBitString):TBitString;
Var
I:Integer;
Begin
SetLength(Result,64);
For I:=0 To Length(DES_REVERSE_IP)-1 Do
Result[I]:=RL[DES_REVERSE_IP[I]-1];
End;
Procedure ReverseSubKeys(Var Keys:TConcatKey);
Var
I,L:Integer;
T:TBitString;
Begin
SetLength(T,48);
L:=Length(Keys);
For I:=0 To (L-1)Div 2 Do
Begin
T:=Keys[I];
Keys[I]:=Keys[(L-I)-1];
Keys[(L-I)-1]:=T;
End;
End;
Function DESEncode(S,Key:String):TBitString;
Var
I:Integer;
K:TBitString;
M:TBitString;
RL:TBitString;
Kplus:TBitString;
SplitKey:TSplitKey;
ConcatKey:TConcatKey;
IPKey:TIPKey;
Begin
K:=AnsiStrToBin(Key);
Kplus:=GetPermutedKey(K);
SplitKey:=GetSplitKey(Kplus);
ConcatKey:=GetConcatKey(SplitKey);
M:=AnsiStrToBin(S);
IPKey:=GetIPKey(M,ConcatKey);
SetLength(RL,64);
For I:=0 To 31 Do
Begin
RL[I]:=IPKey[16].R[I];
RL[I+32]:=IPKey[16].L[I];
End;
RL:=GetReverseIP(RL);
Result:=RL;
End;
Function DESDecode(S,Key:String):TBitString;
Var
I:Integer;
K:TBitString;
M:TBitString;
RL:TBitString;
Kplus:TBitString;
SplitKey:TSplitKey;
ConcatKey:TConcatKey;
IPKey:TIPKey;
Begin
K:=AnsiStrToBin(Key);
Kplus:=GetPermutedKey(K);
SplitKey:=GetSplitKey(Kplus);
ConcatKey:=GetConcatKey(SplitKey);
ReverseSubKeys(ConcatKey);
M:=AnsiStrToBin(S);
IPKey:=GetIPKey(M,ConcatKey);
SetLength(RL,64);
For I:=0 To 31 Do
Begin
RL[I]:=IPKey[16].R[I];
RL[I+32]:=IPKey[16].L[I];
End;
RL:=GetReverseIP(RL);
Result:=RL;
End;
end.
uses DES
Unit1 :
procedure TForm1.Memo1Change(Sender: TObject);
begin
IF Memo1.Text<>'' Then
Memo3.Text:=BinToStr(AnsiStrToBin(Memo1.Text))
Else Memo3.Clear;
Label2.Caption:='Message - ('+IntToStr(Length(Memo1.Text))+' characters)';
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.OnChange(Self);
Edit1.OnChange(Self);
end;
procedure TForm1.Edit1Change(Sender: TObject);
begin
Label4.Caption:=IntToStr(Length(Edit1.Text))+' characters';
end;
procedure TForm1.Memo2Change(Sender: TObject);
begin
IF Memo2.Text<>'' Then
Memo4.Text:=BinToStr(AnsiStrToBin(Memo2.Text))
Else Memo4.Clear;
Label3.Caption:='Encoded message - ('+IntToStr(Length(Memo2.Text))+' characters)';
end;
Crypt :
procedure TForm1.Button1Click(Sender: TObject);
Var
I:Integer;
S:String;
begin
IF ((Length(Memo1.Text)mod 8 <> 0) OR (Length(Edit1.Text)mod 8 <> 0)) Then
Begin
Exit;
End;
SetLength(Data,0);
I:=1;
While I<=Length(Memo1.Text) Do
Begin
S:=Copy(Memo1.Text,I,8);
Data:=ConcatBits([Data,DESEncode(S,Edit1.Text)]);
I:=I+8;
End;
Memo2.Text:=BinToAnsiStr(Data);
end;
Decrypt :
procedure TForm1.Button2Click(Sender: TObject);
var
I:Integer;
begin
IF ((Length(Memo2.Text)mod 8 <> 0) OR (Length(Edit1.Text)mod 8 <> 0)) Then
Begin
Exit;
End;
SetLength(Data,0);
I:=1;
While I<=Length(Memo2.Text) Do
Begin
Data:=ConcatBits([Data,DESDecode(Copy(Memo2.Text,I,8),Edit1.Text)]);
I:=I+8;
End;
Memo1.Text:=BinToAnsiStr(Data);
end;
Keine Kommentare:
Kommentar veröffentlichen