99 lines
2.6 KiB
ObjectPascal

unit cah_rc4;
interface
{$R-} {$Q-}
uses SysUtils, Classes;
type
TRC4KEY = record
state: array[0..255] of Byte;
x: Byte;
y: Byte;
end;
ERC4Error = class(Exception);
procedure MakeRC4KeyByPassword(const Pass: PByte; const PassLen: Integer; out Key: TRC4Key); OVERLOAD;
procedure MakeRC4KeyByPassword(const Pass: String; out Key: TRC4Key); OVERLOAD;
procedure rc4transform(Buffer: PByte; const BufferLen: Integer; Key: TRC4Key); OVERLOAD;
procedure rc4transform(var Buffer: String; Key: TRC4Key); OVERLOAD;
procedure rc4transform(Source, Dest: TStream; const Count: Int64; const Key: TRC4Key); OVERLOAD;
procedure rc4encriptfile(Source, Dest: TStream; const Pass: String); OVERLOAD;
procedure rc4encriptfile(Source, Dest: String; const Pass: String); OVERLOAD;
implementation
procedure MakeRC4KeyByPassword(const Pass: PByte; const PassLen: Integer; out Key: TRC4Key);
var p: PByte;
tmp, k, i, j: Byte;
begin
if PassLen = 0 then
raise ERC4Error.Create('RC4 (InitKey) : Password can not be blank');
for i:= Low(Key.state) to High(Key.state) do
Key.state[i]:= i;
Key.x:= 0;
Key.y:= 0;
k:= 0;
j:= 0;
for i:= Low(Key.state) to High(Key.state) do
begin
j:= j mod PassLen;
tmp:= Key.state[i];
p:= Pass;
Inc(p, j);
Inc(k, tmp + p^);
Inc(j);
Key.state[i]:= Key.state[k];
Key.state[k]:= tmp;
end;
end;
procedure MakeRC4KeyByPassword(const Pass: String; out Key: TRC4Key);
begin
MakeRC4KeyByPassword(@Pass[1], Length(Pass), Key);
end;
procedure rc4transform(Buffer: PByte; const BufferLen: Integer; Key: TRC4Key);
var p: PByte;
tmp: Byte;
i: Integer;
begin
p:= Buffer;
Inc(p, BufferLen - 1);
for i:= 0 to BufferLen - 1 do
begin
Inc(Key.x);
tmp:= Key.state[Key.x];
Inc(Key.y, tmp);
Key.state[Key.x]:= Key.state[Key.y];
Key.state[Key.y]:= tmp;
Inc(tmp, Key.state[Key.x]);
p^:= p^ xor Key.state[tmp];
Dec(p);
end;
end;
procedure rc4transform(var Buffer: String; Key: TRC4Key);
begin
rc4transform(@Buffer[1], Length(Buffer), Key);
end;
procedure rc4transform(Source, Dest: TStream; const Count: Int64; const Key: TRC4Key);
var M: TMemoryStream;
begin
M:= TMemoryStream.Create();
try
M.CopyFrom(Source, Count);
rc4transform(M.Memory, M.Size, Key);
Dest.CopyFrom(M, 0);
finally
M.Free();
end;
end;
procedure rc4encriptfile(Source, Dest: TStream; const Pass: String);
var Key: TRC4KEY;
begin
MakeRC4KeyByPassword(Pass, Key);
rc4transform(Source, Dest, Source.Size, Key);
end;
procedure rc4encriptfile(Source, Dest: String; const Pass: String);
var FS1, FS2: TFileStream;
begin
FS1:= TFileStream.Create(Source, fmOpenRead);
FS2:= TFileStream.Create(Dest, fmCreate);
rc4encriptfile(FS1, FS2, Pass);
FS2.Free;
FS1.Free;
end;
end.