local md5 = {} -- local md5 = { -- _VERSION = "md5.lua 1.1.0", -- _DESCRIPTION = "MD5 computation in Lua (5.1-3, LuaJIT)", -- _URL = "https://github.com/kikito/md5.lua", -- _LICENSE = [[ -- MIT LICENSE -- -- Copyright (c) 2013 Enrique GarcĂ­a Cota + Adam Baldwin + hanzao + Equi 4 Software -- -- Permission is hereby granted, free of charge, to any person obtaining a -- copy of this software and associated documentation files (the -- "Software"), to deal in the Software without restriction, including -- without limitation the rights to use, copy, modify, merge, publish, -- distribute, sublicense, and/or sell copies of the Software, and to -- permit persons to whom the Software is furnished to do so, subject to -- the following conditions: -- -- The above copyright notice and this permission notice shall be included -- in all copies or substantial portions of the Software. -- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -- ]] -- } -- bit lib implementions local char, byte, format, rep, sub = string.char, string.byte, string.format, string.rep, string.sub local bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift local ok, bit = pcall(require, 'bit') local ok_ffi, ffi = pcall(require, 'ffi') if ok then bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift = bit.bor, bit.band, bit.bnot, bit.bxor, bit.rshift, bit.lshift else ok, bit = pcall(require, 'bit32') if ok then bit_not = bit.bnot local tobit = function(n) return n <= 0x7fffffff and n or -(bit_not(n) + 1) end local normalize = function(f) return function(a, b) return tobit(f(tobit(a), tobit(b))) end end bit_or, bit_and, bit_xor = normalize(bit.bor), normalize(bit.band), normalize(bit.bxor) bit_rshift, bit_lshift = normalize(bit.rshift), normalize(bit.lshift) else local function tbl2number(tbl) local result = 0 local power = 1 for i = 1, #tbl do result = result + tbl[i] * power power = power * 2 end return result end local function expand(t1, t2) local big, small = t1, t2 if (#big < #small) then big, small = small, big end -- expand small for i = #small + 1, #big do small[i] = 0 end end local to_bits -- needs to be declared before bit_not bit_not = function(n) local tbl = to_bits(n) local size = math.max(#tbl, 32) for i = 1, size do if (tbl[i] == 1) then tbl[i] = 0 else tbl[i] = 1 end end return tbl2number(tbl) end -- defined as local above to_bits = function(n) if (n < 0) then -- negative return to_bits(bit_not(math.abs(n)) + 1) end -- to bits table local tbl = {} local cnt = 1 local last while n > 0 do last = n % 2 tbl[cnt] = last n = (n - last) / 2 cnt = cnt + 1 end return tbl end bit_or = function(m, n) local tbl_m = to_bits(m) local tbl_n = to_bits(n) expand(tbl_m, tbl_n) local tbl = {} for i = 1, #tbl_m do if (tbl_m[i] == 0 and tbl_n[i] == 0) then tbl[i] = 0 else tbl[i] = 1 end end return tbl2number(tbl) end bit_and = function(m, n) local tbl_m = to_bits(m) local tbl_n = to_bits(n) expand(tbl_m, tbl_n) local tbl = {} for i = 1, #tbl_m do if (tbl_m[i] == 0 or tbl_n[i] == 0) then tbl[i] = 0 else tbl[i] = 1 end end return tbl2number(tbl) end bit_xor = function(m, n) local tbl_m = to_bits(m) local tbl_n = to_bits(n) expand(tbl_m, tbl_n) local tbl = {} for i = 1, #tbl_m do if (tbl_m[i] ~= tbl_n[i]) then tbl[i] = 1 else tbl[i] = 0 end end return tbl2number(tbl) end bit_rshift = function(n, bits) local high_bit = 0 if (n < 0) then -- negative n = bit_not(math.abs(n)) + 1 high_bit = 0x80000000 end local floor = math.floor for i = 1, bits do n = n / 2 n = bit_or(floor(n), high_bit) end return floor(n) end bit_lshift = function(n, bits) if (n < 0) then -- negative n = bit_not(math.abs(n)) + 1 end for i = 1, bits do n = n * 2 end return bit_and(n, 0xFFFFFFFF) end end end -- convert little-endian 32-bit int to a 4-char string local lei2str -- function is defined this way to allow full jit compilation (removing UCLO instruction in LuaJIT) if ok_ffi then local ct_IntType = ffi.typeof("int[1]") lei2str = function(i) return ffi.string(ct_IntType(i), 4) end else lei2str = function(i) local f = function(s) return char(bit_and(bit_rshift(i, s), 255)) end return f(0) .. f(8) .. f(16) .. f(24) end end -- convert raw string to big-endian int local function str2bei(s) local v = 0 for i = 1, #s do v = v * 256 + byte(s, i) end return v end -- convert raw string to little-endian int local str2lei if ok_ffi then local ct_constcharptr = ffi.typeof("const char*") local ct_constintptr = ffi.typeof("const int*") str2lei = function(s) local int = ct_constcharptr(s) return ffi.cast(ct_constintptr, int)[0] end else str2lei = function(s) local v = 0 for i = #s, 1, -1 do v = v * 256 + byte(s, i) end return v end end -- cut up a string in little-endian ints of given size local function cut_le_str(s) return { str2lei(sub(s, 1, 4)), str2lei(sub(s, 5, 8)), str2lei(sub(s, 9, 12)), str2lei(sub(s, 13, 16)), str2lei(sub(s, 17, 20)), str2lei(sub(s, 21, 24)), str2lei(sub(s, 25, 28)), str2lei(sub(s, 29, 32)), str2lei(sub(s, 33, 36)), str2lei(sub(s, 37, 40)), str2lei(sub(s, 41, 44)), str2lei(sub(s, 45, 48)), str2lei(sub(s, 49, 52)), str2lei(sub(s, 53, 56)), str2lei(sub(s, 57, 60)), str2lei(sub(s, 61, 64)), } end -- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh) -- 10/02/2001 jcw@equi4.com local CONSTS = { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 } local f = function(x, y, z) return bit_or(bit_and(x, y), bit_and(-x - 1, z)) end local g = function(x, y, z) return bit_or(bit_and(x, z), bit_and(y, -z - 1)) end local h = function(x, y, z) return bit_xor(x, bit_xor(y, z)) end local i = function(x, y, z) return bit_xor(y, bit_or(x, -z - 1)) end local z = function(ff, a, b, c, d, x, s, ac) a = bit_and(a + ff(b, c, d) + x + ac, 0xFFFFFFFF) -- be *very* careful that left shift does not cause rounding! return bit_or(bit_lshift(bit_and(a, bit_rshift(0xFFFFFFFF, s)), s), bit_rshift(a, 32 - s)) + b end local function transform(A, B, C, D, X) local a, b, c, d = A, B, C, D local t = CONSTS a = z(f, a, b, c, d, X[0], 7, t[1]) d = z(f, d, a, b, c, X[1], 12, t[2]) c = z(f, c, d, a, b, X[2], 17, t[3]) b = z(f, b, c, d, a, X[3], 22, t[4]) a = z(f, a, b, c, d, X[4], 7, t[5]) d = z(f, d, a, b, c, X[5], 12, t[6]) c = z(f, c, d, a, b, X[6], 17, t[7]) b = z(f, b, c, d, a, X[7], 22, t[8]) a = z(f, a, b, c, d, X[8], 7, t[9]) d = z(f, d, a, b, c, X[9], 12, t[10]) c = z(f, c, d, a, b, X[10], 17, t[11]) b = z(f, b, c, d, a, X[11], 22, t[12]) a = z(f, a, b, c, d, X[12], 7, t[13]) d = z(f, d, a, b, c, X[13], 12, t[14]) c = z(f, c, d, a, b, X[14], 17, t[15]) b = z(f, b, c, d, a, X[15], 22, t[16]) a = z(g, a, b, c, d, X[1], 5, t[17]) d = z(g, d, a, b, c, X[6], 9, t[18]) c = z(g, c, d, a, b, X[11], 14, t[19]) b = z(g, b, c, d, a, X[0], 20, t[20]) a = z(g, a, b, c, d, X[5], 5, t[21]) d = z(g, d, a, b, c, X[10], 9, t[22]) c = z(g, c, d, a, b, X[15], 14, t[23]) b = z(g, b, c, d, a, X[4], 20, t[24]) a = z(g, a, b, c, d, X[9], 5, t[25]) d = z(g, d, a, b, c, X[14], 9, t[26]) c = z(g, c, d, a, b, X[3], 14, t[27]) b = z(g, b, c, d, a, X[8], 20, t[28]) a = z(g, a, b, c, d, X[13], 5, t[29]) d = z(g, d, a, b, c, X[2], 9, t[30]) c = z(g, c, d, a, b, X[7], 14, t[31]) b = z(g, b, c, d, a, X[12], 20, t[32]) a = z(h, a, b, c, d, X[5], 4, t[33]) d = z(h, d, a, b, c, X[8], 11, t[34]) c = z(h, c, d, a, b, X[11], 16, t[35]) b = z(h, b, c, d, a, X[14], 23, t[36]) a = z(h, a, b, c, d, X[1], 4, t[37]) d = z(h, d, a, b, c, X[4], 11, t[38]) c = z(h, c, d, a, b, X[7], 16, t[39]) b = z(h, b, c, d, a, X[10], 23, t[40]) a = z(h, a, b, c, d, X[13], 4, t[41]) d = z(h, d, a, b, c, X[0], 11, t[42]) c = z(h, c, d, a, b, X[3], 16, t[43]) b = z(h, b, c, d, a, X[6], 23, t[44]) a = z(h, a, b, c, d, X[9], 4, t[45]) d = z(h, d, a, b, c, X[12], 11, t[46]) c = z(h, c, d, a, b, X[15], 16, t[47]) b = z(h, b, c, d, a, X[2], 23, t[48]) a = z(i, a, b, c, d, X[0], 6, t[49]) d = z(i, d, a, b, c, X[7], 10, t[50]) c = z(i, c, d, a, b, X[14], 15, t[51]) b = z(i, b, c, d, a, X[5], 21, t[52]) a = z(i, a, b, c, d, X[12], 6, t[53]) d = z(i, d, a, b, c, X[3], 10, t[54]) c = z(i, c, d, a, b, X[10], 15, t[55]) b = z(i, b, c, d, a, X[1], 21, t[56]) a = z(i, a, b, c, d, X[8], 6, t[57]) d = z(i, d, a, b, c, X[15], 10, t[58]) c = z(i, c, d, a, b, X[6], 15, t[59]) b = z(i, b, c, d, a, X[13], 21, t[60]) a = z(i, a, b, c, d, X[4], 6, t[61]) d = z(i, d, a, b, c, X[11], 10, t[62]) c = z(i, c, d, a, b, X[2], 15, t[63]) b = z(i, b, c, d, a, X[9], 21, t[64]) return bit_and(A + a, 0xFFFFFFFF), bit_and(B + b, 0xFFFFFFFF), bit_and(C + c, 0xFFFFFFFF), bit_and(D + d, 0xFFFFFFFF) end ---------------------------------------------------------------- local function md5_update(self, s) self.pos = self.pos + #s s = self.buf .. s for ii = 1, #s - 63, 64 do local X = cut_le_str(sub(s, ii, ii + 63)) assert(#X == 16) X[0] = table.remove(X, 1) -- zero based! self.a, self.b, self.c, self.d = transform(self.a, self.b, self.c, self.d, X) end self.buf = sub(s, math.floor(#s / 64) * 64 + 1, #s) return self end local function md5_finish(self) local msgLen = self.pos local padLen = 56 - msgLen % 64 if msgLen % 64 > 56 then padLen = padLen + 64 end if padLen == 0 then padLen = 64 end local s = char(128) .. rep(char(0), padLen - 1) .. lei2str(bit_and(8 * msgLen, 0xFFFFFFFF)) .. lei2str(math.floor(msgLen / 0x20000000)) md5_update(self, s) assert(self.pos % 64 == 0) return lei2str(self.a) .. lei2str(self.b) .. lei2str(self.c) .. lei2str(self.d) end ---------------------------------------------------------------- function md5.new() return { a = CONSTS[65], b = CONSTS[66], c = CONSTS[67], d = CONSTS[68], pos = 0, buf = '', update = md5_update, finish = md5_finish } end function md5.tohex(s) return format("%08x%08x%08x%08x", str2bei(sub(s, 1, 4)), str2bei(sub(s, 5, 8)), str2bei(sub(s, 9, 12)), str2bei(sub(s, 13, 16))) end function md5.sum(s) return md5.new():update(s):finish() end function md5.sumhexa(s) return md5.tohex(md5.sum(s)) end return md5