Difference between revisions of "Module:Md5"

From Dragalia Lost Wiki
Jump to navigation Jump to search
>Eave
(Created page with "-- Lua Module for calculating md5 hash sums -- Needed in order to get absolute file paths for hosted images from Lua modules. local p = {} local md5 = { _VERSION = "md5....")
>Eave
(can use a fixed bit library)
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
-- Lua Module for calculating md5 hash sums
 
-- Lua Module for calculating md5 hash sums
 
-- Needed in order to get absolute file paths for hosted images from Lua modules.
 
-- Needed in order to get absolute file paths for hosted images from Lua modules.
local p = {}
 
 
local md5 = {
 
local md5 = {
 
   _VERSION    = "md5.lua 1.1.0",
 
   _VERSION    = "md5.lua 1.1.0",
Line 38: Line 37:
 
local bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift
 
local bit_or, bit_and, bit_not, bit_xor, bit_rshift, bit_lshift
  
local ok, bit = pcall(require, 'bit')
+
local bit = require('bit32')
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
  
    bit_not = bit.bnot
+
local tobit = function(n)
 +
  return n <= 0x7fffffff and n or -(bit_not(n) + 1)
 +
end
  
    local tobit = function(n)
+
local normalize = function(f)
      return n <= 0x7fffffff and n or -(bit_not(n) + 1)
+
  return function(a,b) return tobit(f(tobit(a), tobit(b))) end
    end
+
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)
+
bit_or, bit_and, bit_xor = normalize(bit.bor), normalize(bit.band), normalize(bit.bxor)
      if(n < 0) then
+
bit_rshift, bit_lshift = normalize(bit.rshift), normalize(bit.lshift)
        -- 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
 
-- convert little-endian 32-bit int to a 4-char string
Line 397: Line 250:
 
end
 
end
  
-- Usage: {{#invoke:Md5|sum|<string to compute hash sum of>}}
+
return md5
function p.sum(frame)
 
  return md5.sum(frame.args[1])
 
end
 
 
 
return p
 

Latest revision as of 02:56, 8 April 2020

Documentation for this module may be created at Module:Md5/doc

-- Lua Module for calculating md5 hash sums
-- Needed in order to get absolute file paths for hosted images from Lua modules.
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 bit = require('bit32')

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)

-- convert little-endian 32-bit int to a 4-char string
local function lei2str(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

-- 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 function str2lei(s)
  local v=0
  for i = #s,1,-1 do
    v = v*256 + byte(s, i)
  end
  return v
end

-- cut up a string in little-endian ints of given size
local function cut_le_str(s,...)
  local o, r = 1, {}
  local args = {...}
  for i=1, #args do
    table.insert(r, str2lei(sub(s, o, o + args[i] - 1)))
    o = o + args[i]
  end
  return r
end

local swap = function (w) return str2bei(lei2str(w)) 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),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4)
    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