include "bin32.s7i";
include "cipher.s7i";
const type: arc4State is sub noCipherState struct
var array char: s is [0 .. 255] times ' ';
var integer: i is 0;
var integer: j is 0;
end struct;
type_implements_interface(arc4State, cipherState);
const func integer: blockSize (RC4) is 0;
const func arc4State: setArc4Key (in string: arc4Key) is func
result
var arc4State: state is arc4State.value;
local
var integer: i is 0;
var integer: j is 0;
var char: temp is ' ';
var char: ch is ' ';
begin
for i range 0 to 255 do
state.s[i] := chr(i);
end for;
for i range 0 to 255 do
ch := arc4Key[succ(i mod length(arc4Key))];
if ord(ch) > 255 then
raise RANGE_ERROR;
end if;
j := (j + ord(state.s[i]) + ord(ch)) mod 256;
temp := state.s[i];
state.s[i] := state.s[j];
state.s[j] := temp;
end for;
end func;
const func cipherState: setCipherKey (RC4, in string: cipherKey,
in string: initializationVector) is
return toInterface(setArc4Key(cipherKey));
const func char: getArc4PseudoRandomByte (inout arc4State: state) is func
result
var char: keystreamChar is ' ';
local
var char: temp is ' ';
begin
state.i := succ(state.i) mod 256;
state.j := (state.j + ord(state.s[state.i])) mod 256;
temp := state.s[state.i];
state.s[state.i] := state.s[state.j];
state.s[state.j] := temp;
keystreamChar := state.s[(ord(state.s[state.i]) + ord(state.s[state.j])) mod 256];
end func;
const func string: encode (inout arc4State: state, in string: plaintext) is func
result
var string: encoded is "";
local
var char: ch is ' ';
var char: keystreamChar is ' ';
begin
for ch range plaintext do
keystreamChar := getArc4PseudoRandomByte(state);
encoded &:= chr(ord(bin32(ord(ch)) >< bin32(ord(keystreamChar))));
end for;
end func;
const func string: decode (inout arc4State: state, in string: encoded) is func
result
var string: plaintext is "";
local
var char: ch is ' ';
var char: keystreamChar is ' ';
begin
for ch range encoded do
keystreamChar := getArc4PseudoRandomByte(state);
plaintext &:= chr(ord(bin32(ord(ch)) >< bin32(ord(keystreamChar))));
end for;
end func;