xtool/contrib/fundamentals/Cipher/flcCipherRC4.pas

149 lines
6.0 KiB
ObjectPascal

{******************************************************************************}
{ }
{ Library: Fundamentals 5.00 }
{ File name: flcCipherRC4.pas }
{ File version: 5.06 }
{ Description: RC4 cipher routines }
{ }
{ Copyright: Copyright (c) 2007-2020, David J Butler }
{ All rights reserved. }
{ This file is licensed under the BSD License. }
{ See http://www.opensource.org/licenses/bsd-license.php }
{ Redistribution and use in source and binary forms, with }
{ or without modification, are permitted provided that }
{ the following conditions are met: }
{ Redistributions of source code must retain the above }
{ copyright notice, this list of conditions and the }
{ following disclaimer. }
{ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND }
{ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED }
{ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED }
{ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A }
{ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL }
{ THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, }
{ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR }
{ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, }
{ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF }
{ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) }
{ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER }
{ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING }
{ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE }
{ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE }
{ POSSIBILITY OF SUCH DAMAGE. }
{ }
{ Github: https://github.com/fundamentalslib }
{ E-mail: fundamentals.library at gmail.com }
{ }
{ References: }
{ }
{ * www.mozilla.org/projects/security/pki/nss/ }
{ draft-kaukonen-cipher-arcfour-03.txt }
{ }
{ Revision history: }
{ }
{ 2007/01/05 4.01 Initial version. }
{ }
{******************************************************************************}
{$INCLUDE flcCipher.inc}
unit flcCipherRC4;
interface
{ }
{ RC4 }
{ Also known as Arcfour. }
{ }
type
TRC4SBox = packed array[Byte] of Byte;
TRC4Context = packed record
S : TRC4SBox;
SI : Byte;
SJ : Byte;
end;
PRC4Context = ^TRC4Context;
procedure RC4Init(const Key; const KeySize: Integer; var Context: TRC4Context);
procedure RC4Buffer(var Context: TRC4Context; var Buffer; const BufferSize: NativeInt);
implementation
uses
{ Cipher }
flcCipherUtils;
{ }
{ RC4 }
{ }
procedure RC4Init(const Key; const KeySize: Integer; var Context: TRC4Context);
type
TRC4KeyBuffer = array[Byte] of Byte;
PRC4KeyBuffer = ^TRC4KeyBuffer;
var I, J, T : Byte;
K : PRC4KeyBuffer;
begin
// Validate parameters
if KeySize > 256 then
raise ECipher.Create(CipherError_InvalidKeySize, 'Maximum RC4 key length is 256');
if KeySize < 1 then
raise ECipher.Create(CipherError_InvalidKeySize, 'Minimum RC4 key length is 1');
// Prepare RC4 context
with Context do
begin
for I := 0 to 255 do
S[I] := I;
K := @Key;
J := 0;
for I := 0 to 255 do
begin
J := Byte(Byte(J + S[I]) + K^[I mod KeySize]);
T := S[I];
S[I] := S[J];
S[J] := T;
end;
SI := 0;
SJ := 0;
end;
end;
procedure RC4Buffer(var Context: TRC4Context; var Buffer; const BufferSize: NativeInt);
var
SI : Byte;
SJ : Byte;
P : PByte;
F : NativeInt;
T : Byte;
U : Byte;
begin
SI := Context.SI;
SJ := Context.SJ;
P := @Buffer;
for F := 0 to BufferSize - 1 do
begin
SI := Byte(SI + 1);
T := Context.S[SI];
SJ := Byte(SJ + T);
U := Context.S[SJ];
Context.S[SI] := U;
Context.S[SJ] := T;
T := Byte(T + U);
T := Context.S[T];
P^ := P^ xor T;
Inc(P);
end;
Context.SI := SI;
Context.SJ := SJ;
end;
end.