mirror of
https://github.com/StephenGenusa/DCPCrypt.git
synced 2025-06-12 21:57:27 +02:00
453 lines
12 KiB
ObjectPascal
453 lines
12 KiB
ObjectPascal
![]() |
{******************************************************************************}
|
||
|
{* DCPcrypt v2.1 written by David Barton (crypto@cityinthesky.co.uk) **********}
|
||
|
{******************************************************************************}
|
||
|
{* A binary compatible implementation of Ice and it's variants ****************}
|
||
|
{******************************************************************************}
|
||
|
{* Copyright (c) 1999-2002 David Barton *}
|
||
|
{* Permission is hereby granted, free of charge, to any person obtaining a *}
|
||
|
{* copy of this software and associated documentation files (the "Software"), *}
|
||
|
{* to deal in the Software without restriction, including without limitation *}
|
||
|
{* the rights to use, copy, modify, merge, publish, distribute, sublicense, *}
|
||
|
{* and/or sell copies of the Software, and to permit persons to whom the *}
|
||
|
{* Software is furnished to do so, subject to the following conditions: *}
|
||
|
{* *}
|
||
|
{* The above copyright notice and this permission notice shall be included in *}
|
||
|
{* all copies or substantial portions of the Software. *}
|
||
|
{* *}
|
||
|
{* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *}
|
||
|
{* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *}
|
||
|
{* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *}
|
||
|
{* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *}
|
||
|
{* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *}
|
||
|
{* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *}
|
||
|
{* DEALINGS IN THE SOFTWARE. *}
|
||
|
{******************************************************************************}
|
||
|
unit DCPice;
|
||
|
|
||
|
{$INCLUDE '..\dcp.inc'}
|
||
|
|
||
|
interface
|
||
|
uses
|
||
|
Classes, Sysutils, DCPcrypt2, DCPconst, DCPblockciphers;
|
||
|
|
||
|
type
|
||
|
TDCP_customice= class(TDCP_blockcipher64)
|
||
|
protected
|
||
|
rounds: dword;
|
||
|
ik_keysched: array[0..31,0..2] of dword;
|
||
|
function f(p, sk: dword): dword;
|
||
|
procedure key_sched_build(kb: pwordarray; n: dword; keyrot: pdwordarray);
|
||
|
procedure InitIce(const Key; Size: longword; n: dword);
|
||
|
public
|
||
|
procedure Burn; override;
|
||
|
procedure EncryptECB(const InData; var OutData); override;
|
||
|
procedure DecryptECB(const InData; var OutData); override;
|
||
|
constructor Create(AOwner: TComponent); override;
|
||
|
end;
|
||
|
|
||
|
TDCP_ice= class(TDCP_customice)
|
||
|
protected
|
||
|
procedure InitKey(const Key; Size: longword); override;
|
||
|
public
|
||
|
class function GetId: integer; override;
|
||
|
class function GetAlgorithm: string; override;
|
||
|
class function GetMaxKeySize: integer; override;
|
||
|
class function SelfTest: boolean; override;
|
||
|
end;
|
||
|
|
||
|
TDCP_thinice= class(TDCP_customice)
|
||
|
protected
|
||
|
procedure InitKey(const Key; Size: longword); override;
|
||
|
public
|
||
|
class function GetId: integer; override;
|
||
|
class function GetAlgorithm: string; override;
|
||
|
class function GetMaxKeySize: integer; override;
|
||
|
class function SelfTest: boolean; override;
|
||
|
end;
|
||
|
|
||
|
TDCP_ice2= class(TDCP_customice)
|
||
|
protected
|
||
|
procedure InitKey(const Key; Size: longword); override;
|
||
|
public
|
||
|
class function GetId: integer; override;
|
||
|
class function GetAlgorithm: string; override;
|
||
|
class function GetMaxKeySize: integer; override;
|
||
|
class function SelfTest: boolean; override;
|
||
|
end;
|
||
|
|
||
|
{******************************************************************************}
|
||
|
{******************************************************************************}
|
||
|
implementation
|
||
|
{$R-}{$Q-}
|
||
|
|
||
|
{$IFDEF DELPHIXE2_UP}
|
||
|
{$POINTERMATH ON}
|
||
|
{$ENDIF}
|
||
|
|
||
|
var
|
||
|
ice_sbox: array[0..3,0..1023] of dword;
|
||
|
ice_sboxdone: boolean;
|
||
|
|
||
|
const
|
||
|
ice_smod: array[0..3,0..3] of dword= (
|
||
|
(333, 313, 505, 369),
|
||
|
(379, 375, 319, 391),
|
||
|
(361, 445, 451, 397),
|
||
|
(397, 425, 395, 505));
|
||
|
ice_sxor: array[0..3,0..3] of dword= (
|
||
|
($83, $85, $9b, $cd),
|
||
|
($cc, $a7, $ad, $41),
|
||
|
($4b, $2e, $d4, $33),
|
||
|
($ea, $cb, $2e, $04));
|
||
|
ice_keyrot: array[0..15] of dword= (
|
||
|
0, 1, 2, 3, 2, 1, 3, 0,
|
||
|
1, 3, 2, 0, 3, 1, 0, 2);
|
||
|
ice_pbox: array[0..31] of dword= (
|
||
|
$00000001, $00000080, $00000400, $00002000,
|
||
|
$00080000, $00200000, $01000000, $40000000,
|
||
|
$00000008, $00000020, $00000100, $00004000,
|
||
|
$00010000, $00800000, $04000000, $20000000,
|
||
|
$00000004, $00000010, $00000200, $00008000,
|
||
|
$00020000, $00400000, $08000000, $10000000,
|
||
|
$00000002, $00000040, $00000800, $00001000,
|
||
|
$00040000, $00100000, $02000000, $80000000);
|
||
|
|
||
|
function SwapDword(a: dword): dword;
|
||
|
begin
|
||
|
Result:= ((a and $FF) shl 24) or ((a and $FF00) shl 8) or ((a and $FF0000) shr 8) or ((a and $FF000000) shr 24);
|
||
|
end;
|
||
|
|
||
|
{******************************************************************************}
|
||
|
function gf_mult(a, b, m: dword): dword;
|
||
|
var
|
||
|
res: dword;
|
||
|
begin
|
||
|
res:= 0;
|
||
|
while b<> 0 do
|
||
|
begin
|
||
|
if (b and 1)<> 0 then
|
||
|
res:= res xor a;
|
||
|
a:= a shl 1;
|
||
|
b:= b shr 1;
|
||
|
if a>= 256 then
|
||
|
a:= a xor m;
|
||
|
end;
|
||
|
Result:= res;
|
||
|
end;
|
||
|
|
||
|
function gf_exp7(b, m: dword): dword;
|
||
|
var
|
||
|
x: dword;
|
||
|
begin
|
||
|
if b= 0 then
|
||
|
Result:= 0
|
||
|
else
|
||
|
begin
|
||
|
x:= gf_mult(b,b,m);
|
||
|
x:= gf_mult(b,x,m);
|
||
|
x:= gf_mult(x,x,m);
|
||
|
Result:= gf_mult(b,x,m);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function ice_perm32(x: dword): dword;
|
||
|
var
|
||
|
res: dword;
|
||
|
pbox: pdword;
|
||
|
begin
|
||
|
res:= 0;
|
||
|
pbox:= @ice_pbox;
|
||
|
while x<> 0 do
|
||
|
begin
|
||
|
if (x and 1)<> 0 then
|
||
|
res:= res or pbox^;
|
||
|
Inc(pbox);
|
||
|
x:= x shr 1;
|
||
|
end;
|
||
|
Result:= res;
|
||
|
end;
|
||
|
|
||
|
procedure ice_sboxes_init;
|
||
|
var
|
||
|
i, col, row: dword;
|
||
|
x: dword;
|
||
|
begin
|
||
|
for i:= 0 to 1023 do
|
||
|
begin
|
||
|
col:= (i shr 1) and $FF;
|
||
|
row:= (i and 1) or ((i and $200) shr 8);
|
||
|
x:= gf_exp7(col xor ice_sxor[0,row],ice_smod[0,row]) shl 24;
|
||
|
ice_sbox[0,i]:= ice_perm32(x);
|
||
|
x:= gf_exp7(col xor ice_sxor[1,row],ice_smod[1,row]) shl 16;
|
||
|
ice_sbox[1,i]:= ice_perm32(x);
|
||
|
x:= gf_exp7(col xor ice_sxor[2,row],ice_smod[2,row]) shl 8;
|
||
|
ice_sbox[2,i]:= ice_perm32(x);
|
||
|
x:= gf_exp7(col xor ice_sxor[3,row],ice_smod[3,row]);
|
||
|
ice_sbox[3,i]:= ice_perm32(x);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TDCP_customice.f(p, sk: dword): dword;
|
||
|
var
|
||
|
tl, tr, al, ar: dword;
|
||
|
begin
|
||
|
tl:= ((p shr 16) and $3ff) or (((p shr 14) or (p shl 18)) and $ffc00);
|
||
|
tr:= (p and $3ff) or ((p shl 2) and $ffc00);
|
||
|
al:= ik_keysched[sk,2] and (tl xor tr);
|
||
|
ar:= al xor tr;
|
||
|
al:= al xor tl;
|
||
|
al:= al xor ik_keysched[sk,0];
|
||
|
ar:= ar xor ik_keysched[sk,1];
|
||
|
Result:= ice_sbox[0,al shr 10] or ice_sbox[1,al and $3ff] or
|
||
|
ice_sbox[2,ar shr 10] or ice_sbox[3,ar and $3ff];
|
||
|
end;
|
||
|
|
||
|
|
||
|
procedure TDCP_customice.key_sched_build(kb: pwordarray; n: dword; keyrot: pdwordarray);
|
||
|
var
|
||
|
i, j, k, kr: dword;
|
||
|
keys: pdwordarray;
|
||
|
currentsk: pdword;
|
||
|
currentkb: pword;
|
||
|
bit: dword;
|
||
|
begin
|
||
|
for i:= 0 to 7 do
|
||
|
begin
|
||
|
kr:= keyrot^[i];
|
||
|
keys:= @ik_keysched[n+i];
|
||
|
for j:= 0 to 2 do
|
||
|
keys^[j]:= 0;
|
||
|
for j:= 0 to 14 do
|
||
|
begin
|
||
|
currentsk:= @keys^[j mod 3];
|
||
|
for k:= 0 to 3 do
|
||
|
begin
|
||
|
currentkb:= @kb^[(kr + k) and 3];
|
||
|
bit:= currentkb^ and 1;
|
||
|
currentsk^:= (currentsk^ shl 1) or bit;
|
||
|
currentkb^:= (currentkb^ shr 1) or ((bit xor 1) shl 15);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TDCP_customice.InitIce(const Key; Size: longword; n: dword);
|
||
|
var
|
||
|
i, j: dword;
|
||
|
kb: array[0..3] of word;
|
||
|
keyb: array[0..15] of byte;
|
||
|
begin
|
||
|
FillChar(keyb,Sizeof(keyb),0);
|
||
|
Move(key,keyb,Size div 8);
|
||
|
if n> 0 then
|
||
|
rounds:= 16 * n
|
||
|
else
|
||
|
rounds:= 8;
|
||
|
|
||
|
if rounds= 8 then
|
||
|
begin
|
||
|
for i:= 0 to 3 do // Adrien Reboisson - was "for i:= 0 to 4 do"
|
||
|
kb[3 - i]:= (keyb[i*2] shl 8) or keyb[i*2 + 1];
|
||
|
key_sched_build(@kb,0,@ice_keyrot);
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
for i:= 0 to (n-1) do
|
||
|
begin
|
||
|
for j:= 0 to 3 do
|
||
|
kb[3-j]:= (keyb[i*8 + j*2] shl 8) or keyb[i*8 + j*2 + 1];
|
||
|
key_sched_build(@kb,i*8,@ice_keyrot);
|
||
|
key_sched_build(@kb,rounds - 8 - i*8,@ice_keyrot[8]);
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TDCP_customice.Burn;
|
||
|
begin
|
||
|
FillChar(ik_keysched,Sizeof(ik_keysched),0);
|
||
|
Rounds:= 0;
|
||
|
inherited Burn;
|
||
|
end;
|
||
|
|
||
|
procedure TDCP_customice.EncryptECB(const InData; var OutData);
|
||
|
var
|
||
|
i, l, r: dword;
|
||
|
begin
|
||
|
if not fInitialized then
|
||
|
raise EDCP_blockcipher.Create('Cipher not initialized');
|
||
|
l:= SwapDWord(Pdword(@InData)^);
|
||
|
r:= SwapDWord(Pdword(PointerToInt(@InData)+4)^);
|
||
|
i:= 0;
|
||
|
while i< rounds do
|
||
|
begin
|
||
|
l:= l xor f(r,i);
|
||
|
r:= r xor f(l,i+1);
|
||
|
Inc(i,2);
|
||
|
end;
|
||
|
Pdword(@OutData)^:= SwapDWord(r);
|
||
|
Pdword(PointerToInt(@OutData)+4)^:= SwapDWord(l);
|
||
|
end;
|
||
|
|
||
|
procedure TDCP_customice.DecryptECB(const InData; var OutData);
|
||
|
var
|
||
|
l, r: dword;
|
||
|
i: integer;
|
||
|
begin
|
||
|
if not fInitialized then
|
||
|
raise EDCP_blockcipher.Create('Cipher not initialized');
|
||
|
l:= SwapDWord(Pdword(@InData)^);
|
||
|
r:= SwapDWord(Pdword(PointerToInt(@InData)+4)^);
|
||
|
i:= rounds-1;
|
||
|
while i> 0 do
|
||
|
begin
|
||
|
l:= l xor f(r,i);
|
||
|
r:= r xor f(l,i-1);
|
||
|
Dec(i,2);
|
||
|
end;
|
||
|
Pdword(@OutData)^:= SwapDWord(r);
|
||
|
Pdword(PointerToInt(@OutData)+4)^:= SwapDWord(l);
|
||
|
end;
|
||
|
|
||
|
constructor TDCP_customice.Create(AOwner: TComponent);
|
||
|
begin
|
||
|
inherited Create(AOwner);
|
||
|
if not ice_sboxdone then
|
||
|
begin
|
||
|
ice_sboxes_init;
|
||
|
ice_sboxdone:= true;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
{******************************************************************************}
|
||
|
class function TDCP_ice.GetMaxKeySize: integer;
|
||
|
begin
|
||
|
Result:= 64;
|
||
|
end;
|
||
|
|
||
|
class function TDCP_ice.GetID: integer;
|
||
|
begin
|
||
|
Result:= DCP_ice;
|
||
|
end;
|
||
|
|
||
|
class function TDCP_ice.GetAlgorithm: string;
|
||
|
begin
|
||
|
Result:= 'Ice';
|
||
|
end;
|
||
|
|
||
|
class function TDCP_ice.SelfTest: boolean;
|
||
|
const
|
||
|
Key1: array[0..7] of byte= ($de,$ad,$be,$ef,$01,$23,$45,$67);
|
||
|
InData1: array[0..7] of byte= ($fe,$dc,$ba,$98,$76,$54,$32,$10);
|
||
|
OutData1: array[0..7] of byte= ($7d,$6e,$f1,$ef,$30,$d4,$7a,$96);
|
||
|
var
|
||
|
Cipher: TDCP_ice;
|
||
|
Data: array[0..7] of byte;
|
||
|
begin
|
||
|
FillChar(Data, SizeOf(Data), 0);
|
||
|
Cipher:= TDCP_ice.Create(nil);
|
||
|
Cipher.Init(Key1,Sizeof(Key1)*8,nil);
|
||
|
Cipher.EncryptECB(InData1,Data);
|
||
|
Result:= boolean(CompareMem(@Data,@OutData1,Sizeof(Data)));
|
||
|
Cipher.Reset;
|
||
|
Cipher.DecryptECB(Data,Data);
|
||
|
Result:= boolean(CompareMem(@Data,@InData1,Sizeof(Data))) and Result;
|
||
|
Cipher.Burn;
|
||
|
Cipher.Free;
|
||
|
end;
|
||
|
|
||
|
procedure TDCP_ice.InitKey(const Key; Size: longword);
|
||
|
begin
|
||
|
InitIce(Key,Size,1);
|
||
|
end;
|
||
|
|
||
|
{******************************************************************************}
|
||
|
class function TDCP_thinice.GetMaxKeySize: integer;
|
||
|
begin
|
||
|
Result:= 64;
|
||
|
end;
|
||
|
|
||
|
class function TDCP_thinice.GetID: integer;
|
||
|
begin
|
||
|
Result:= DCP_thinice;
|
||
|
end;
|
||
|
|
||
|
class function TDCP_thinice.GetAlgorithm: string;
|
||
|
begin
|
||
|
Result:= 'Thin Ice';
|
||
|
end;
|
||
|
|
||
|
class function TDCP_thinice.SelfTest: boolean;
|
||
|
const
|
||
|
Key1: array[0..7] of byte= ($de,$ad,$be,$ef,$01,$23,$45,$67);
|
||
|
InData1: array[0..7] of byte= ($fe,$dc,$ba,$98,$76,$54,$32,$10);
|
||
|
OutData1: array[0..7] of byte= ($de,$24,$0d,$83,$a0,$0a,$9c,$c0);
|
||
|
var
|
||
|
Cipher: TDCP_thinice;
|
||
|
Data: array[0..7] of byte;
|
||
|
begin
|
||
|
FillChar(Data, SizeOf(Data), 0);
|
||
|
Cipher:= TDCP_thinice.Create(nil);
|
||
|
Cipher.Init(Key1,Sizeof(Key1)*8,nil);
|
||
|
Cipher.EncryptECB(InData1,Data);
|
||
|
Result:= boolean(CompareMem(@Data,@OutData1,Sizeof(Data)));
|
||
|
Cipher.Reset;
|
||
|
Cipher.DecryptECB(Data,Data);
|
||
|
Result:= boolean(CompareMem(@Data,@InData1,Sizeof(Data))) and Result;
|
||
|
Cipher.Burn;
|
||
|
Cipher.Free;
|
||
|
end;
|
||
|
|
||
|
procedure TDCP_thinice.InitKey(const Key; Size: longword);
|
||
|
begin
|
||
|
InitIce(Key,Size,0);
|
||
|
end;
|
||
|
|
||
|
{******************************************************************************}
|
||
|
class function TDCP_ice2.GetMaxKeySize: integer;
|
||
|
begin
|
||
|
Result:= 128;
|
||
|
end;
|
||
|
|
||
|
class function TDCP_ice2.GetID: integer;
|
||
|
begin
|
||
|
Result:= DCP_ice2;
|
||
|
end;
|
||
|
|
||
|
class function TDCP_ice2.GetAlgorithm: string;
|
||
|
begin
|
||
|
Result:= 'Ice2';
|
||
|
end;
|
||
|
|
||
|
class function TDCP_ice2.SelfTest: boolean;
|
||
|
const
|
||
|
Key1: array[0..15] of byte=
|
||
|
($00,$11,$22,$33,$44,$55,$66,$77,$88,$99,$aa,$bb,$cc,$dd,$ee,$ff);
|
||
|
InData1: array[0..7] of byte= ($fe,$dc,$ba,$98,$76,$54,$32,$10);
|
||
|
OutData1: array[0..7] of byte= ($f9,$48,$40,$d8,$69,$72,$f2,$1c);
|
||
|
var
|
||
|
Cipher: TDCP_ice2;
|
||
|
Data: array[0..7] of byte;
|
||
|
begin
|
||
|
FillChar(Data, SizeOf(Data), 0);
|
||
|
Cipher:= TDCP_ice2.Create(nil);
|
||
|
Cipher.Init(Key1,Sizeof(Key1)*8,nil);
|
||
|
Cipher.EncryptECB(InData1,Data);
|
||
|
Result:= boolean(CompareMem(@Data,@OutData1,Sizeof(Data)));
|
||
|
Cipher.Reset;
|
||
|
Cipher.DecryptECB(Data,Data);
|
||
|
Result:= boolean(CompareMem(@Data,@InData1,Sizeof(Data))) and Result;
|
||
|
Cipher.Burn;
|
||
|
Cipher.Free;
|
||
|
end;
|
||
|
|
||
|
procedure TDCP_ice2.InitKey(const Key; Size: longword);
|
||
|
begin
|
||
|
InitIce(Key,Size,2);
|
||
|
end;
|
||
|
|
||
|
|
||
|
initialization
|
||
|
ice_sboxdone:= false;
|
||
|
|
||
|
end.
|