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