99 lines
2.6 KiB
ObjectPascal
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.
|