You've already forked lazarus-dcpcrypt
mirror of
https://git.code.sf.net/p/lazarus-ccr/dcpcrypt
synced 2025-11-28 21:49:45 +02:00
* My previous attempt was not thorough enough and I missed a lot of details. * More testing was done and now it seems to work correctly on 32-bit and 64-bit Linux.
212 lines
6.8 KiB
ObjectPascal
212 lines
6.8 KiB
ObjectPascal
{******************************************************************************}
|
|
{* DCPcrypt v2.0 written by David Barton (crypto@cityinthesky.co.uk) **********}
|
|
{******************************************************************************}
|
|
{* A binary compatible implementation of RC4 **********************************}
|
|
{******************************************************************************}
|
|
{* 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 DCPrc4;
|
|
|
|
{$MODE Delphi}
|
|
|
|
interface
|
|
uses
|
|
Classes, Sysutils, DCPcrypt2, DCPconst;
|
|
|
|
type
|
|
TDCP_rc4= class(TDCP_cipher)
|
|
protected
|
|
KeyData, KeyOrg: array[0..255] of byte;
|
|
public
|
|
class function GetID: integer; override;
|
|
class function GetAlgorithm: string; override;
|
|
class function GetMaxKeySize: integer; override;
|
|
class function SelfTest: boolean; override;
|
|
procedure Init(const Key; Size: longword; InitVector: pointer); override;
|
|
procedure Reset; override;
|
|
procedure Burn; override;
|
|
procedure Encrypt(const InData; var OutData; Size: longword); override;
|
|
procedure Decrypt(const InData; var OutData; Size: longword); override;
|
|
end;
|
|
|
|
{******************************************************************************}
|
|
{******************************************************************************}
|
|
implementation
|
|
{$R-}{$Q-}
|
|
|
|
class function TDCP_rc4.GetID: integer;
|
|
begin
|
|
Result:= DCP_rc4;
|
|
end;
|
|
|
|
class function TDCP_rc4.GetAlgorithm: string;
|
|
begin
|
|
Result:= 'RC4';
|
|
end;
|
|
|
|
class function TDCP_rc4.GetMaxKeySize: integer;
|
|
begin
|
|
Result:= 2048;
|
|
end;
|
|
|
|
class function TDCP_rc4.SelfTest: boolean;
|
|
const
|
|
Key1: array[0..4] of byte= ($61,$8A,$63,$D2,$FB);
|
|
InData1: array[0..4] of byte= ($DC,$EE,$4C,$F9,$2C);
|
|
OutData1: array[0..4] of byte= ($F1,$38,$29,$C9,$DE);
|
|
var
|
|
Cipher: TDCP_rc4;
|
|
Data: array[0..4] of byte;
|
|
begin
|
|
Cipher:= TDCP_rc4.Create(nil);
|
|
Cipher.Init(Key1,Sizeof(Key1)*8,nil);
|
|
Cipher.Encrypt(InData1,Data,Sizeof(Data));
|
|
Result:= boolean(CompareMem(@Data,@OutData1,Sizeof(Data)));
|
|
Cipher.Reset;
|
|
Cipher.Decrypt(Data,Data,Sizeof(Data));
|
|
Result:= boolean(CompareMem(@Data,@InData1,Sizeof(Data))) and Result;
|
|
Cipher.Burn;
|
|
Cipher.Free;
|
|
end;
|
|
|
|
procedure TDCP_rc4.Init(const Key; Size: longword; InitVector: pointer);
|
|
var
|
|
i, j, t: longword;
|
|
xKey: array[0..255] of byte;
|
|
begin
|
|
if fInitialized then
|
|
Burn;
|
|
inherited Init(Key,Size,nil);
|
|
Size:= Size div 8;
|
|
i:= 0;
|
|
while i< 255 do
|
|
begin
|
|
KeyData[i]:= i;
|
|
xKey[i]:= PByte(pointer(@Key)+(i mod Size))^;
|
|
KeyData[i+1]:= i+1;
|
|
xKey[i+1]:= PByte(pointer(@Key)+((i+1) mod Size))^;
|
|
KeyData[i+2]:= i+2;
|
|
xKey[i+2]:= PByte(pointer(@Key)+((i+2) mod Size))^;
|
|
KeyData[i+3]:= i+3;
|
|
xKey[i+3]:= PByte(pointer(@Key)+((i+3) mod Size))^;
|
|
KeyData[i+4]:= i+4;
|
|
xKey[i+4]:= PByte(pointer(@Key)+((i+4) mod Size))^;
|
|
KeyData[i+5]:= i+5;
|
|
xKey[i+5]:= PByte(pointer(@Key)+((i+5) mod Size))^;
|
|
KeyData[i+6]:= i+6;
|
|
xKey[i+6]:= PByte(pointer(@Key)+((i+6) mod Size))^;
|
|
KeyData[i+7]:= i+7;
|
|
xKey[i+7]:= PByte(pointer(@Key)+((i+7) mod Size))^;
|
|
Inc(i,8);
|
|
end;
|
|
j:= 0;
|
|
i:= 0;
|
|
while i< 255 do
|
|
begin
|
|
j:= (j+KeyData[i]+xKey[i]) and $FF;
|
|
t:= KeyData[i];
|
|
KeyData[i]:= KeyData[j];
|
|
KeyData[j]:= t;
|
|
j:= (j+KeyData[i+1]+xKey[i+1]) and $FF;
|
|
t:= KeyData[i+1];
|
|
KeyData[i+1]:= KeyData[j];
|
|
KeyData[j]:= t;
|
|
j:= (j+KeyData[i+2]+xKey[i+2]) and $FF;
|
|
t:= KeyData[i+2];
|
|
KeyData[i+2]:= KeyData[j];
|
|
KeyData[j]:= t;
|
|
j:= (j+KeyData[i+3]+xKey[i+3]) and $FF;
|
|
t:= KeyData[i+3];
|
|
KeyData[i+3]:= KeyData[j];
|
|
KeyData[j]:= t;
|
|
j:= (j+KeyData[i+4]+xKey[i+4]) and $FF;
|
|
t:= KeyData[i+4];
|
|
KeyData[i+4]:= KeyData[j];
|
|
KeyData[j]:= t;
|
|
j:= (j+KeyData[i+5]+xKey[i+5]) and $FF;
|
|
t:= KeyData[i+5];
|
|
KeyData[i+5]:= KeyData[j];
|
|
KeyData[j]:= t;
|
|
j:= (j+KeyData[i+6]+xKey[i+6]) and $FF;
|
|
t:= KeyData[i+6];
|
|
KeyData[i+6]:= KeyData[j];
|
|
KeyData[j]:= t;
|
|
j:= (j+KeyData[i+7]+xKey[i+7]) and $FF;
|
|
t:= KeyData[i+7];
|
|
KeyData[i+7]:= KeyData[j];
|
|
KeyData[j]:= t;
|
|
Inc(i,8);
|
|
end;
|
|
Move(KeyData,KeyOrg,Sizeof(KeyOrg));
|
|
end;
|
|
|
|
procedure TDCP_rc4.Reset;
|
|
begin
|
|
Move(KeyOrg,KeyData,Sizeof(KeyData));
|
|
end;
|
|
|
|
procedure TDCP_rc4.Burn;
|
|
begin
|
|
FillChar(KeyOrg,Sizeof(KeyOrg),$FF);
|
|
FillChar(KeyData,Sizeof(KeyData),$FF);
|
|
inherited Burn;
|
|
end;
|
|
|
|
procedure TDCP_rc4.Encrypt(const InData; var OutData; Size: longword);
|
|
var
|
|
i, j, t, k: longword;
|
|
begin
|
|
if not fInitialized then
|
|
raise EDCP_cipher.Create('Cipher not initialized');
|
|
i:= 0; j:= 0;
|
|
for k:= 0 to Size-1 do
|
|
begin
|
|
i:= (i + 1) and $FF;
|
|
t:= KeyData[i];
|
|
j:= (j + t) and $FF;
|
|
KeyData[i]:= KeyData[j];
|
|
KeyData[j]:= t;
|
|
t:= (t + KeyData[i]) and $FF;
|
|
Pbytearray(@OutData)^[k]:= Pbytearray(@InData)^[k] xor KeyData[t];
|
|
end;
|
|
end;
|
|
|
|
procedure TDCP_rc4.Decrypt(const InData; var OutData; Size: longword);
|
|
var
|
|
i, j, t, k: longword;
|
|
begin
|
|
if not fInitialized then
|
|
raise EDCP_cipher.Create('Cipher not initialized');
|
|
i:= 0; j:= 0;
|
|
for k:= 0 to Size-1 do
|
|
begin
|
|
i:= (i + 1) and $FF;
|
|
t:= KeyData[i];
|
|
j:= (j + t) and $FF;
|
|
KeyData[i]:= KeyData[j];
|
|
KeyData[j]:= t;
|
|
t:= (t + KeyData[i]) and $FF;
|
|
Pbytearray(@OutData)^[k]:= Pbytearray(@InData)^[k] xor KeyData[t];
|
|
end;
|
|
end;
|
|
|
|
|
|
end.
|