142 lines
3.5 KiB
Text
142 lines
3.5 KiB
Text
-- demo\rosetta\ISAAC_Cipher.exw
|
|
|
|
sequence randrsl = repeat(0,256)
|
|
integer randcnt
|
|
|
|
sequence mm
|
|
atom aa,bb,cc
|
|
|
|
function r32(object a)
|
|
if sequence(a) then
|
|
for i=1 to length(a) do
|
|
a[i] = r32(a[i])
|
|
end for
|
|
return a
|
|
end if
|
|
if a<0 then a+=#100000000 end if
|
|
return remainder(a,#100000000)
|
|
end function
|
|
|
|
function shl(atom word, integer bits)
|
|
return r32(word*power(2,bits))
|
|
end function
|
|
|
|
function shr(atom v, integer bits)
|
|
return floor(v/power(2,bits))
|
|
end function
|
|
|
|
procedure Isaac()
|
|
cc += 1; -- cc just gets incremented once per 256 results
|
|
bb += cc; -- then combined with bb
|
|
for i=1 to 256 do
|
|
atom x = mm[i]
|
|
switch mod(i-1,4) do
|
|
case 0: aa := xor_bits(aa,shl(aa,13))
|
|
case 1: aa := xor_bits(aa,shr(aa, 6))
|
|
case 2: aa := xor_bits(aa,shl(aa, 2))
|
|
case 3: aa := xor_bits(aa,shr(aa,16))
|
|
end switch
|
|
aa = r32(mm[xor_bits(i-1,#80)+1]+aa)
|
|
atom y := mm[and_bits(shr(x,2),#FF)+1]+aa+bb
|
|
mm[i] := y;
|
|
bb := r32(mm[and_bits(shr(y,10),#FF)+1] + x)
|
|
randrsl[i]:= bb;
|
|
end for
|
|
randcnt = 1
|
|
end procedure
|
|
|
|
function mix(sequence a8)
|
|
atom {a,b,c,d,e,f,g,h} = a8
|
|
a = xor_bits(a,shl(b,11)); {d,b} = r32({d+a,b+c});
|
|
b = xor_bits(b,shr(c, 2)); {e,c} = r32({e+b,c+d});
|
|
c = xor_bits(c,shl(d, 8)); {f,d} = r32({f+c,d+e});
|
|
d = xor_bits(d,shr(e,16)); {g,e} = r32({g+d,e+f});
|
|
e = xor_bits(e,shl(f,10)); {h,f} = r32({h+e,f+g});
|
|
f = xor_bits(f,shr(g, 4)); {a,g} = r32({a+f,g+h});
|
|
g = xor_bits(g,shl(h, 8)); {b,h} = r32({b+g,h+a});
|
|
h = xor_bits(h,shr(a, 9)); {c,a} = r32({c+h,a+b});
|
|
a8 = {a,b,c,d,e,f,g,h}
|
|
return a8
|
|
end function
|
|
|
|
procedure iRandInit()
|
|
{aa,bb,cc} = {0,0,0}
|
|
sequence a8 = repeat(#9e3779b9,8) -- the golden ratio
|
|
for i=1 to 4 do -- scramble it
|
|
a8 = mix(a8)
|
|
end for
|
|
for i=1 to 255 by 8 do
|
|
a8 = mix(sq_add(a8,randrsl[i..i+7]))
|
|
mm[i..i+7] = a8
|
|
end for
|
|
for i=1 to 255 by 8 do
|
|
a8 = mix(r32(sq_add(a8,mm[i..i+7])))
|
|
mm[i..i+7] = a8
|
|
end for
|
|
Isaac() -- fill in the first set of results
|
|
end procedure
|
|
|
|
procedure iSeed(string seed)
|
|
mm = repeat(0,256)
|
|
randrsl = repeat(0,256)
|
|
randrsl[1..min(length(seed),256)] = seed
|
|
iRandInit()
|
|
end procedure
|
|
|
|
function randch()
|
|
atom res = mod(randrsl[randcnt],95)+32
|
|
randcnt += 1
|
|
if randcnt>256 then
|
|
Isaac()
|
|
end if
|
|
return res
|
|
end function
|
|
|
|
function Vernam(string msg)
|
|
string res = ""
|
|
for i=1 to length(msg) do
|
|
res &= xor_bits(msg[i],randch())
|
|
end for
|
|
return res
|
|
end function
|
|
|
|
function Caesar(integer ch, shift)
|
|
return ' '+mod(ch-' '+shift,95)
|
|
end function
|
|
|
|
enum ENCRYPT = +1,
|
|
DECRYPT = -1
|
|
|
|
function Vigenere(string msg, integer mode)
|
|
string res = ""
|
|
for i=1 to length(msg) do
|
|
res &= Caesar(msg[i],randch()*mode)
|
|
end for
|
|
return res
|
|
end function
|
|
|
|
constant string msg = "a Top Secret secret",
|
|
key = "this is my secret key"
|
|
|
|
iSeed(key)
|
|
string xctx := Vernam(msg),
|
|
mctx := Vigenere(msg,ENCRYPT)
|
|
|
|
iSeed(key)
|
|
string xptx := Vernam(xctx),
|
|
mptx := Vigenere(mctx,DECRYPT)
|
|
|
|
function ascii2hex(string s)
|
|
string res = ""
|
|
for i=1 to length(s) do
|
|
res &= sprintf("%02x",s[i])
|
|
end for
|
|
return res
|
|
end function
|
|
|
|
printf(1,"Message: %s\n",{msg})
|
|
printf(1,"Key : %s\n",{key})
|
|
printf(1,"XOR : %s\n",{ascii2hex(xctx)})
|
|
printf(1,"MOD : %s\n",{ascii2hex(mctx)})
|
|
printf(1,"XOR dcr: %s\n",{xptx})
|
|
printf(1,"MOD dcr: %s\n",{mptx})
|