-- An MD5 mplementation in Lua, requires bitlib -- Written by Jean-Claude Wippler -- 10/02/2001 jcw@equi4.com -- Original source available at http://www.equi4.com/md5/md5calc.lua -- Transformed for use in GroupCalendar by John Stephen gGroupCalendarMD5 = { }; function GroupCalendarMD5_Initialize() gGroupCalendarMD5.Mask32 = tonumber("ffffffff", 16); gGroupCalendarMD5.Consts = {}; local vConstants = { "d76aa478", "e8c7b756", "242070db", "c1bdceee", "f57c0faf", "4787c62a", "a8304613", "fd469501", "698098d8", "8b44f7af", "ffff5bb1", "895cd7be", "6b901122", "fd987193", "a679438e", "49b40821", "f61e2562", "c040b340", "265e5a51", "e9b6c7aa", "d62f105d", "02441453", "d8a1e681", "e7d3fbc8", "21e1cde6", "c33707d6", "f4d50d87", "455a14ed", "a9e3e905", "fcefa3f8", "676f02d9", "8d2a4c8a", "fffa3942", "8771f681", "6d9d6122", "fde5380c", "a4beea44", "4bdecfa9", "f6bb4b60", "bebfbc70", "289b7ec6", "eaa127fa", "d4ef3085", "04881d05", "d9d4d039", "e6db99e5", "1fa27cf8", "c4ac5665", "f4292244", "432aff97", "ab9423a7", "fc93a039", "655b59c3", "8f0ccc92", "ffeff47d", "85845dd1", "6fa87e4f", "fe2ce6e0", "a3014314", "4e0811a1", "f7537e82", "bd3af235", "2ad7d2bb", "eb86d391", "67452301", "efcdab89", "98badcfe", "10325476", }; for vIndex, vConstStr in vConstants do gGroupCalendarMD5.Consts[vIndex] = tonumber(vConstStr, 16); end end function GroupCalendarMD5_f(x, y, z) return bit.bor(bit.band(x, y), bit.band(-x - 1, z)); end function GroupCalendarMD5_g(x, y, z) return bit.bor(bit.band(x, z), bit.band(y, -z - 1)); end function GroupCalendarMD5_h(x, y, z) return bit.bxor(x, bit.bxor(y, z)); end function GroupCalendarMD5_i(x, y, z) return bit.bxor(y, bit.bor(x, -z - 1)); end function GroupCalendarMD5_z(f,a,b,c,d,x,s,ac) a = bit.band(a + f(b, c, d) + x + ac, gGroupCalendarMD5.Mask32); -- be *very* careful that left shift does not cause rounding! return bit.bor(bit.lshift(bit.band(a, bit.rshift(gGroupCalendarMD5.Mask32, s)), s), bit.rshift(a, 32 - s)) + b; end function GroupCalendarMD5_Transform(A,B,C,D,X) local a, b, c, d = A, B, C, D; local t = gGroupCalendarMD5.Consts; -- Round 1 a=GroupCalendarMD5_z(GroupCalendarMD5_f,a,b,c,d,X[ 1], 7,t[ 1]) d=GroupCalendarMD5_z(GroupCalendarMD5_f,d,a,b,c,X[ 2],12,t[ 2]) c=GroupCalendarMD5_z(GroupCalendarMD5_f,c,d,a,b,X[ 3],17,t[ 3]) b=GroupCalendarMD5_z(GroupCalendarMD5_f,b,c,d,a,X[ 4],22,t[ 4]) a=GroupCalendarMD5_z(GroupCalendarMD5_f,a,b,c,d,X[ 5], 7,t[ 5]) d=GroupCalendarMD5_z(GroupCalendarMD5_f,d,a,b,c,X[ 6],12,t[ 6]) c=GroupCalendarMD5_z(GroupCalendarMD5_f,c,d,a,b,X[ 7],17,t[ 7]) b=GroupCalendarMD5_z(GroupCalendarMD5_f,b,c,d,a,X[ 8],22,t[ 8]) a=GroupCalendarMD5_z(GroupCalendarMD5_f,a,b,c,d,X[ 9], 7,t[ 9]) d=GroupCalendarMD5_z(GroupCalendarMD5_f,d,a,b,c,X[10],12,t[10]) c=GroupCalendarMD5_z(GroupCalendarMD5_f,c,d,a,b,X[11],17,t[11]) b=GroupCalendarMD5_z(GroupCalendarMD5_f,b,c,d,a,X[12],22,t[12]) a=GroupCalendarMD5_z(GroupCalendarMD5_f,a,b,c,d,X[13], 7,t[13]) d=GroupCalendarMD5_z(GroupCalendarMD5_f,d,a,b,c,X[14],12,t[14]) c=GroupCalendarMD5_z(GroupCalendarMD5_f,c,d,a,b,X[15],17,t[15]) b=GroupCalendarMD5_z(GroupCalendarMD5_f,b,c,d,a,X[16],22,t[16]) -- Round 2 a=GroupCalendarMD5_z(GroupCalendarMD5_g,a,b,c,d,X[ 2], 5,t[17]) d=GroupCalendarMD5_z(GroupCalendarMD5_g,d,a,b,c,X[ 7], 9,t[18]) c=GroupCalendarMD5_z(GroupCalendarMD5_g,c,d,a,b,X[12],14,t[19]) b=GroupCalendarMD5_z(GroupCalendarMD5_g,b,c,d,a,X[ 1],20,t[20]) a=GroupCalendarMD5_z(GroupCalendarMD5_g,a,b,c,d,X[ 6], 5,t[21]) d=GroupCalendarMD5_z(GroupCalendarMD5_g,d,a,b,c,X[11], 9,t[22]) c=GroupCalendarMD5_z(GroupCalendarMD5_g,c,d,a,b,X[16],14,t[23]) b=GroupCalendarMD5_z(GroupCalendarMD5_g,b,c,d,a,X[ 5],20,t[24]) a=GroupCalendarMD5_z(GroupCalendarMD5_g,a,b,c,d,X[10], 5,t[25]) d=GroupCalendarMD5_z(GroupCalendarMD5_g,d,a,b,c,X[15], 9,t[26]) c=GroupCalendarMD5_z(GroupCalendarMD5_g,c,d,a,b,X[ 4],14,t[27]) b=GroupCalendarMD5_z(GroupCalendarMD5_g,b,c,d,a,X[ 9],20,t[28]) a=GroupCalendarMD5_z(GroupCalendarMD5_g,a,b,c,d,X[14], 5,t[29]) d=GroupCalendarMD5_z(GroupCalendarMD5_g,d,a,b,c,X[ 3], 9,t[30]) c=GroupCalendarMD5_z(GroupCalendarMD5_g,c,d,a,b,X[ 8],14,t[31]) b=GroupCalendarMD5_z(GroupCalendarMD5_g,b,c,d,a,X[13],20,t[32]) -- Round 3 a=GroupCalendarMD5_z(GroupCalendarMD5_h,a,b,c,d,X[ 6], 4,t[33]) d=GroupCalendarMD5_z(GroupCalendarMD5_h,d,a,b,c,X[ 9],11,t[34]) c=GroupCalendarMD5_z(GroupCalendarMD5_h,c,d,a,b,X[12],16,t[35]) b=GroupCalendarMD5_z(GroupCalendarMD5_h,b,c,d,a,X[15],23,t[36]) a=GroupCalendarMD5_z(GroupCalendarMD5_h,a,b,c,d,X[ 2], 4,t[37]) d=GroupCalendarMD5_z(GroupCalendarMD5_h,d,a,b,c,X[ 5],11,t[38]) c=GroupCalendarMD5_z(GroupCalendarMD5_h,c,d,a,b,X[ 8],16,t[39]) b=GroupCalendarMD5_z(GroupCalendarMD5_h,b,c,d,a,X[11],23,t[40]) a=GroupCalendarMD5_z(GroupCalendarMD5_h,a,b,c,d,X[14], 4,t[41]) d=GroupCalendarMD5_z(GroupCalendarMD5_h,d,a,b,c,X[ 1],11,t[42]) c=GroupCalendarMD5_z(GroupCalendarMD5_h,c,d,a,b,X[ 4],16,t[43]) b=GroupCalendarMD5_z(GroupCalendarMD5_h,b,c,d,a,X[ 7],23,t[44]) a=GroupCalendarMD5_z(GroupCalendarMD5_h,a,b,c,d,X[10], 4,t[45]) d=GroupCalendarMD5_z(GroupCalendarMD5_h,d,a,b,c,X[13],11,t[46]) c=GroupCalendarMD5_z(GroupCalendarMD5_h,c,d,a,b,X[16],16,t[47]) b=GroupCalendarMD5_z(GroupCalendarMD5_h,b,c,d,a,X[ 3],23,t[48]) -- Round 4 a=GroupCalendarMD5_z(GroupCalendarMD5_i,a,b,c,d,X[ 1], 6,t[49]) d=GroupCalendarMD5_z(GroupCalendarMD5_i,d,a,b,c,X[ 8],10,t[50]) c=GroupCalendarMD5_z(GroupCalendarMD5_i,c,d,a,b,X[15],15,t[51]) b=GroupCalendarMD5_z(GroupCalendarMD5_i,b,c,d,a,X[ 6],21,t[52]) a=GroupCalendarMD5_z(GroupCalendarMD5_i,a,b,c,d,X[13], 6,t[53]) d=GroupCalendarMD5_z(GroupCalendarMD5_i,d,a,b,c,X[ 4],10,t[54]) c=GroupCalendarMD5_z(GroupCalendarMD5_i,c,d,a,b,X[11],15,t[55]) b=GroupCalendarMD5_z(GroupCalendarMD5_i,b,c,d,a,X[ 2],21,t[56]) a=GroupCalendarMD5_z(GroupCalendarMD5_i,a,b,c,d,X[ 9], 6,t[57]) d=GroupCalendarMD5_z(GroupCalendarMD5_i,d,a,b,c,X[16],10,t[58]) c=GroupCalendarMD5_z(GroupCalendarMD5_i,c,d,a,b,X[ 7],15,t[59]) b=GroupCalendarMD5_z(GroupCalendarMD5_i,b,c,d,a,X[14],21,t[60]) a=GroupCalendarMD5_z(GroupCalendarMD5_i,a,b,c,d,X[ 5], 6,t[61]) d=GroupCalendarMD5_z(GroupCalendarMD5_i,d,a,b,c,X[12],10,t[62]) c=GroupCalendarMD5_z(GroupCalendarMD5_i,c,d,a,b,X[ 3],15,t[63]) b=GroupCalendarMD5_z(GroupCalendarMD5_i,b,c,d,a,X[10],21,t[64]) return A+a,B+b,C+c,D+d end function GroupCalendarMD5_Calc(s) local msgLen=strlen(s) local padLen=56-bit.mod(msgLen,64) if bit.mod(msgLen,64)>56 then padLen=padLen+64 end if padLen==0 then padLen=64 end s = s..strchar(128)..strrep(strchar(0),padLen-1) s = s..GroupCalendar_LEToString(8*msgLen)..GroupCalendar_LEToString(0) local a, b, c, d = gGroupCalendarMD5.Consts[65], gGroupCalendarMD5.Consts[66], gGroupCalendarMD5.Consts[67], gGroupCalendarMD5.Consts[68]; for i = 1, strlen(s), 64 do local X = GroupCalendar_SliceStringToLEs(strsub(s, i, i + 63)); a, b, c, d = GroupCalendarMD5_Transform(a, b, c, d, X); end local swap = function (w) return GroupCalendar_StringToBE4(GroupCalendar_LEToString(w)) end return format("%08x%08x%08x%08x", swap(a), swap(b), swap(c), swap(d)); end -- convert little-endian 32-bit int to a 4-char string function GroupCalendar_LEToString(i) i = math.floor(i); local f = function (s) return strchar(bit.band(bit.rshift(i,s),255)) end return f(0)..f(8)..f(16)..f(24) end -- convert raw string to big-endian int function GroupCalendar_StringToBE4(str) return 256 * (256 * (256 * strbyte(str, 1) + strbyte(str, 2)) + strbyte(str, 3)) + strbyte(str, 4); end -- cut up a string in little-endian ints of given size function GroupCalendar_SliceStringToLEs(s) local r = {}; local o = 1; for i = 1, 16 do local str = strsub(s, o, o + 3); r[i] = 256 * (256 * (256 * strbyte(str, 4) + strbyte(str, 3)) + strbyte(str, 2)) + strbyte(str, 1); o = o + 4; end return r; end function GroupCalendarMD5_Verify() s0 = 'message digest' s1 = 'abcdefghijklmnopqrstuvwxyz' s2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' s3 = '12345678901234567890123456789012345678901234567890123456789012345678901234567890' if GroupCalendarMD5_Calc('') ~= 'd41d8cd98f00b204e9800998ecf8427e' then Calendar_ErrorMessage("GroupCalendarMD5: Test 1 failed"); return; end if GroupCalendarMD5_Calc('a') ~= '0cc175b9c0f1b6a831c399e269772661' then Calendar_ErrorMessage("GroupCalendarMD5: Test 2 failed"); return; end if GroupCalendarMD5_Calc('abc') ~= '900150983cd24fb0d6963f7d28e17f72' then Calendar_ErrorMessage("GroupCalendarMD5: Test 3 failed"); return; end if GroupCalendarMD5_Calc(s0) ~= 'f96b697d7cb7938d525a2f31aaf161d0' then Calendar_ErrorMessage("GroupCalendarMD5: Test 4 failed"); return; end if GroupCalendarMD5_Calc(s1) ~= 'c3fcd3d76192e4007dfb496cca67e13b' then Calendar_ErrorMessage("GroupCalendarMD5: Test 5 failed"); return; end if GroupCalendarMD5_Calc(s2) ~= 'd174ab98d277d9f5a5611c2c9f419d9f' then Calendar_ErrorMessage("GroupCalendarMD5: Test 6 failed"); return; end if GroupCalendarMD5_Calc(s3) ~= '57edf4a22be3c955ac49da2e2107b67a' then Calendar_ErrorMessage("GroupCalendarMD5: Test 7 failed"); return; end Calendar_DebugMessage("GroupCalendarMD5: All tests passed"); end function GroupCalendarMD5_CheckPerformance() if 1 then sizes={10,50,100,500,1000,5000,10000} for i=1,getn(sizes) do local s=strrep(' ',sizes[i]) debugprofilestart(); for j=1,10 do GroupCalendarMD5_Calc(s) end local elapsed = math.floor(debugprofilestop() / 10); Calendar_DebugMessage(format('%6d bytes: %4d ms', sizes[i], elapsed)) end end end