1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
-- rnd experimental hash ( min 256 bit output )
--TODO: rewrite with arrays, only final step convert to string. + better whole accumulator
if not crypto then crypto = {} end
local rndm = 2^31 − 1; --C++11's minstd_rand
local rnda = 48271; -- generator
local rndseed = 0;
local random = function(n)
rndseed = (rnda*rndseed)% rndm;
return rndseed % n
end
local hash_ = function(input,seed)
local n = 128-32+1; -- Z_97, 97 prime
local m = 32;
local ret = {};input = input or "";
rndseed = seed;
local key = {};
local out = {};
for i=1, string.len(input) do
key[i] = random(n) -- generate keys from password
out[i] = string.byte(input,i)-m
if out[i] == -6 then out[i] = 96 end -- conversion back
end
local c0 = 1; -- this serves as accumulator too
for i=1, string.len(input) do
local offset=key[i]
local c = out[i];
for j = 1,string.len(input) do c0 = c0 + (out[j])^3; c0 = c0 % n end
c = (c+c0+offset) % n;
out[i] = c
end
rndseed = rndseed+c0
for i = 1, string.len(input) do
if out[i] == 96 then out[i]=-6 end -- 32 + 96 = 128 (bad char)
ret[#ret+1] = string.char(m+out[i])
end
return table.concat(ret,""),rndseed
end
crypto.rndhash = function(text)
local length = string.len(text);
if length<32 then text = text .. string.rep(" ", 32-length) end
local seed = 0; -- accumulator
local ret = text; for i = 1, 10 do ret,seed = hash_(ret,seed) end
return ret
end
|