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.