134 lines
4.5 KiB
Lua
134 lines
4.5 KiB
Lua
local _M = {}
|
|
|
|
_M.to_bin = function (str)
|
|
local data = ''
|
|
str:lower():gsub('([a-z0-9])([a-z0-9])', function (d1, d2)
|
|
d1 = _M.hexdigit2int(d1)
|
|
d2 = _M.hexdigit2int(d2)
|
|
data = (data .. string.char(d1 * 16 + d2))
|
|
end)
|
|
return data
|
|
end
|
|
_M.to_hex = function (str)
|
|
local data = ''
|
|
for i=1,#str,1 do
|
|
data = (data .. ("%02x"):format(str:byte(i)))
|
|
end
|
|
return data
|
|
end
|
|
|
|
_M.hexdigit2int = function (ch)
|
|
local b = ch:byte()
|
|
if b >= ('a'):byte() then
|
|
return 10 + (b - ('a'):byte())
|
|
elseif b >= ('0'):byte() then
|
|
return b - ('0'):byte()
|
|
else
|
|
_M.assert(false)
|
|
end
|
|
end
|
|
|
|
_M.b64 = (function ()
|
|
-- character table string
|
|
local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
|
-- encoding
|
|
local function enc(data)
|
|
return ((data:gsub('.', function(x)
|
|
local r,b='',x:byte()
|
|
for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
|
|
return r;
|
|
end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
|
|
if (#x < 6) then return '' end
|
|
local c=0
|
|
for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
|
|
return b:sub(c+1,c+1)
|
|
end)..({ '', '==', '=' })[#data%3+1])
|
|
end
|
|
|
|
-- decoding
|
|
local function dec(data)
|
|
data = string.gsub(data, '[^'..b..'=]', '')
|
|
return (data:gsub('.', function(x)
|
|
if (x == '=') then return '' end
|
|
local r,f='',(b:find(x)-1)
|
|
for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
|
|
return r;
|
|
end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
|
|
if (#x ~= 8) then return '' end
|
|
local c=0
|
|
for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
|
|
return string.char(c)
|
|
end))
|
|
end
|
|
return {
|
|
encode = enc,
|
|
decode = dec,
|
|
}
|
|
end)()
|
|
|
|
_M.sha2 = require("sha2")
|
|
|
|
_M.hmac = (function ()
|
|
--local hmac = require 'hmac'
|
|
local sha2 = _M.sha2
|
|
|
|
-- these hmac-ize routine is from https://github.com/bjc/prosody/blob/master/util/hmac.lua.
|
|
-- thanks!
|
|
local s_char = string.char;
|
|
local s_gsub = string.gsub;
|
|
local s_rep = string.rep;
|
|
local xor_map = {0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;1;0;3;2;5;4;7;6;9;8;11;10;13;12;15;14;2;3;0;1;6;7;4;5;10;11;8;9;14;15;12;13;3;2;1;0;7;6;5;4;11;10;9;8;15;14;13;12;4;5;6;7;0;1;2;3;12;13;14;15;8;9;10;11;5;4;7;6;1;0;3;2;13;12;15;14;9;8;11;10;6;7;4;5;2;3;0;1;14;15;12;13;10;11;8;9;7;6;5;4;3;2;1;0;15;14;13;12;11;10;9;8;8;9;10;11;12;13;14;15;0;1;2;3;4;5;6;7;9;8;11;10;13;12;15;14;1;0;3;2;5;4;7;6;10;11;8;9;14;15;12;13;2;3;0;1;6;7;4;5;11;10;9;8;15;14;13;12;3;2;1;0;7;6;5;4;12;13;14;15;8;9;10;11;4;5;6;7;0;1;2;3;13;12;15;14;9;8;11;10;5;4;7;6;1;0;3;2;14;15;12;13;10;11;8;9;6;7;4;5;2;3;0;1;15;14;13;12;11;10;9;8;7;6;5;4;3;2;1;0;};
|
|
local function xor(x, y)
|
|
local lowx, lowy = x % 16, y % 16;
|
|
local hix, hiy = (x - lowx) / 16, (y - lowy) / 16;
|
|
local lowr, hir = xor_map[lowx * 16 + lowy + 1], xor_map[hix * 16 + hiy + 1];
|
|
local r = hir * 16 + lowr;
|
|
return r;
|
|
end
|
|
local opadc, ipadc = s_char(0x5c), s_char(0x36);
|
|
local ipad_map = {};
|
|
local opad_map = {};
|
|
for i=0,255 do
|
|
ipad_map[s_char(i)] = s_char(xor(0x36, i));
|
|
opad_map[s_char(i)] = s_char(xor(0x5c, i));
|
|
end
|
|
local function hmac(key, message, hash, blocksize)
|
|
if #key > blocksize then
|
|
key = hash(key)
|
|
end
|
|
|
|
local padding = blocksize - #key;
|
|
local ipad = s_gsub(key, ".", ipad_map)..s_rep(ipadc, padding);
|
|
local opad = s_gsub(key, ".", opad_map)..s_rep(opadc, padding);
|
|
|
|
return hash(opad..hash(ipad..message))
|
|
end
|
|
local sha256 = function (data)
|
|
local text = sha2.hash256(data)
|
|
return _M.to_bin(text)
|
|
end
|
|
local digest_routines = {
|
|
hex = _M.to_hex,
|
|
base64 = _M.b64.encode
|
|
}
|
|
local hmac_sha256 = function (key, data, digest)
|
|
local bin = hmac(key, data, sha256, 64)
|
|
-- print(_M.to_hex(bin))
|
|
--local bin = _M.to_bin("8BDD6729CE0F580B7424921D5F0CFD1F1642243762CBA71FFCC8FABCFC72608B")
|
|
return digest_routines[digest] and digest_routines[digest](bin) or bin
|
|
end
|
|
|
|
local hmac_sha1 = function (key, data, digest)
|
|
local bin = sha1.sha1_bin(key, data)
|
|
return digest_routines[digest] and digest_routines[digest](bin) or bin
|
|
end
|
|
|
|
_M.hmac_by = {
|
|
sha256 = hmac_sha256,
|
|
sha1 = hmac_sha1,
|
|
}
|
|
return hmac_sha256
|
|
end)()
|
|
|
|
return _M
|