You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koreader/frontend/MD5.lua

234 lines
6.9 KiB
Lua

local ffi = require "ffi"
local bit = require "bit"
local bxor = bit.bxor
local bnot = bit.bnot
local band = bit.band
local bor = bit.bor
local rshift = bit.rshift
local lshift = bit.lshift
require "memutils"
require "stringzutils"
ffi.cdef[[
typedef struct MD5Context {
uint32_t buf[4];
uint32_t bits[2];
unsigned char input[64];
} MD5_CTX;
]]
MD5_CTX = ffi.typeof("MD5_CTX");
function byteReverse(buf, len)
end
function F1(x, y, z) return bxor(z, band(x, bxor(y, z))) end
function F2(x, y, z) return F1(z, x, y) end
function F3(x, y, z) return bxor(x, y, z) end
function F4(x, y, z) return bxor(y, bor(x, bnot(z))) end
function MD5STEP(f, w, x, y, z, data, s)
w = w + f(x, y, z) + data;
w = bor(lshift(w,s), rshift(w,(32-s)))
w = w + x;
return w;
end
function printmd5ctx(ctx)
for i=0,3 do
print(string.format("ctx.buf[%d]: 0x%x", i, ctx.buf[i]));
end
print(string.format("ctx.bits[0]: %d", ctx.bits[0]));
print(string.format("ctx.bits[1]: %d", ctx.bits[1]));
end
-- Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
-- initialization constants.
function MD5Init(ctx)
ctx.buf[0] = 0x67452301;
ctx.buf[1] = 0xefcdab89;
ctx.buf[2] = 0x98badcfe;
ctx.buf[3] = 0x10325476;
ctx.bits[0] = 0;
ctx.bits[1] = 0;
end
function MD5Transform(buf, input)
local a = buf[0];
local b = buf[1];
local c = buf[2];
local d = buf[3];
a = MD5STEP(F1, a, b, c, d, input[0] + 0xd76aa478, 7);
d = MD5STEP(F1, d, a, b, c, input[1] + 0xe8c7b756, 12);
c = MD5STEP(F1, c, d, a, b, input[2] + 0x242070db, 17);
b = MD5STEP(F1, b, c, d, a, input[3] + 0xc1bdceee, 22);
a = MD5STEP(F1, a, b, c, d, input[4] + 0xf57c0faf, 7);
d = MD5STEP(F1, d, a, b, c, input[5] + 0x4787c62a, 12);
c = MD5STEP(F1, c, d, a, b, input[6] + 0xa8304613, 17);
b = MD5STEP(F1, b, c, d, a, input[7] + 0xfd469501, 22);
a = MD5STEP(F1, a, b, c, d, input[8] + 0x698098d8, 7);
d = MD5STEP(F1, d, a, b, c, input[9] + 0x8b44f7af, 12);
c = MD5STEP(F1, c, d, a, b, input[10] + 0xffff5bb1, 17);
b = MD5STEP(F1, b, c, d, a, input[11] + 0x895cd7be, 22);
a = MD5STEP(F1, a, b, c, d, input[12] + 0x6b901122, 7);
d = MD5STEP(F1, d, a, b, c, input[13] + 0xfd987193, 12);
c = MD5STEP(F1, c, d, a, b, input[14] + 0xa679438e, 17);
b = MD5STEP(F1, b, c, d, a, input[15] + 0x49b40821, 22);
a = MD5STEP(F2, a, b, c, d, input[1] + 0xf61e2562, 5);
d = MD5STEP(F2, d, a, b, c, input[6] + 0xc040b340, 9);
c = MD5STEP(F2, c, d, a, b, input[11] + 0x265e5a51, 14);
b = MD5STEP(F2, b, c, d, a, input[0] + 0xe9b6c7aa, 20);
a = MD5STEP(F2, a, b, c, d, input[5] + 0xd62f105d, 5);
d = MD5STEP(F2, d, a, b, c, input[10] + 0x02441453, 9);
c = MD5STEP(F2, c, d, a, b, input[15] + 0xd8a1e681, 14);
b = MD5STEP(F2, b, c, d, a, input[4] + 0xe7d3fbc8, 20);
a = MD5STEP(F2, a, b, c, d, input[9] + 0x21e1cde6, 5);
d = MD5STEP(F2, d, a, b, c, input[14] + 0xc33707d6, 9);
c = MD5STEP(F2, c, d, a, b, input[3] + 0xf4d50d87, 14);
b = MD5STEP(F2, b, c, d, a, input[8] + 0x455a14ed, 20);
a = MD5STEP(F2, a, b, c, d, input[13] + 0xa9e3e905, 5);
d = MD5STEP(F2, d, a, b, c, input[2] + 0xfcefa3f8, 9);
c = MD5STEP(F2, c, d, a, b, input[7] + 0x676f02d9, 14);
b = MD5STEP(F2, b, c, d, a, input[12] + 0x8d2a4c8a, 20);
a = MD5STEP(F3, a, b, c, d, input[5] + 0xfffa3942, 4);
d = MD5STEP(F3, d, a, b, c, input[8] + 0x8771f681, 11);
c = MD5STEP(F3, c, d, a, b, input[11] + 0x6d9d6122, 16);
b = MD5STEP(F3, b, c, d, a, input[14] + 0xfde5380c, 23);
a = MD5STEP(F3, a, b, c, d, input[1] + 0xa4beea44, 4);
d = MD5STEP(F3, d, a, b, c, input[4] + 0x4bdecfa9, 11);
c = MD5STEP(F3, c, d, a, b, input[7] + 0xf6bb4b60, 16);
b = MD5STEP(F3, b, c, d, a, input[10] + 0xbebfbc70, 23);
a = MD5STEP(F3, a, b, c, d, input[13] + 0x289b7ec6, 4);
d = MD5STEP(F3, d, a, b, c, input[0] + 0xeaa127fa, 11);
c = MD5STEP(F3, c, d, a, b, input[3] + 0xd4ef3085, 16);
b = MD5STEP(F3, b, c, d, a, input[6] + 0x04881d05, 23);
a = MD5STEP(F3, a, b, c, d, input[9] + 0xd9d4d039, 4);
d = MD5STEP(F3, d, a, b, c, input[12] + 0xe6db99e5, 11);
c = MD5STEP(F3, c, d, a, b, input[15] + 0x1fa27cf8, 16);
b = MD5STEP(F3, b, c, d, a, input[2] + 0xc4ac5665, 23);
a = MD5STEP(F4, a, b, c, d, input[0] + 0xf4292244, 6);
d = MD5STEP(F4, d, a, b, c, input[7] + 0x432aff97, 10);
c = MD5STEP(F4, c, d, a, b, input[14] + 0xab9423a7, 15);
b = MD5STEP(F4, b, c, d, a, input[5] + 0xfc93a039, 21);
a = MD5STEP(F4, a, b, c, d, input[12] + 0x655b59c3, 6);
d = MD5STEP(F4, d, a, b, c, input[3] + 0x8f0ccc92, 10);
c = MD5STEP(F4, c, d, a, b, input[10] + 0xffeff47d, 15);
b = MD5STEP(F4, b, c, d, a, input[1] + 0x85845dd1, 21);
a = MD5STEP(F4, a, b, c, d, input[8] + 0x6fa87e4f, 6);
d = MD5STEP(F4, d, a, b, c, input[15] + 0xfe2ce6e0, 10);
c = MD5STEP(F4, c, d, a, b, input[6] + 0xa3014314, 15);
b = MD5STEP(F4, b, c, d, a, input[13] + 0x4e0811a1, 21);
a = MD5STEP(F4, a, b, c, d, input[4] + 0xf7537e82, 6);
d = MD5STEP(F4, d, a, b, c, input[11] + 0xbd3af235, 10);
c = MD5STEP(F4, c, d, a, b, input[2] + 0x2ad7d2bb, 15);
b = MD5STEP(F4, b, c, d, a, input[9] + 0xeb86d391, 21);
buf[0] = (buf[0] + a)%0xffffffff;
buf[1] = (buf[1] + b)%0xffffffff;
buf[2] = (buf[2] + c)%0xffffffff;
buf[3] = (buf[3] + d)%0xffffffff;
end
function MD5Update(ctx, buf, len)
local t;
t = ctx.bits[0];
ctx.bits[0] = t + lshift( len, 3)
if (ctx.bits[0] < t) then
ctx.bits[1] = ctx.bits[1] + 1;
end
ctx.bits[1] = ctx.bits[1] + rshift(len, 29);
t = band(rshift(t, 3), 0x3f);
if (t > 0) then
p = ffi.cast("unsigned char *", ctx.input + t);
t = 64 - t;
if (len < t) then
memcpy(p, buf, len);
return;
end
memcpy(p, buf, t);
byteReverse(ctx.input, 16);
MD5Transform(ctx.buf, ffi.cast("uint32_t *", ctx.input));
buf = buf + t;
len = len - t;
end
while (len >= 64) do
memcpy(ctx.input, buf, 64);
byteReverse(ctx.input, 16);
MD5Transform(ctx.buf, ffi.cast("uint32_t *", ctx.input));
buf = buf + 64;
len = len - 64;
end
memcpy(ctx.input, buf, len);
end
function MD5Final(digest, ctx)
local count;
local p;
count = band(rshift(ctx.bits[0], 3), 0x3F);
p = ctx.input + count;
p[0] = 0x80;
p = p + 1;
count = 64 - 1 - count;
if (count < 8) then
memset(p, 0, count);
byteReverse(ctx.input, 16);
MD5Transform(ctx.buf, ffi.cast("uint32_t *", ctx.input));
memset(ctx.input, 0, 56);
else
memset(p, 0, count - 8);
end
byteReverse(ctx.input, 14);
ffi.cast("uint32_t *", ctx.input)[14] = ctx.bits[0];
ffi.cast("uint32_t *", ctx.input)[15] = ctx.bits[1];
MD5Transform(ctx.buf, ffi.cast("uint32_t *", ctx.input));
byteReverse(ffi.cast("unsigned char *",ctx.buf), 4);
memcpy(digest, ctx.buf, 16);
memset(ffi.cast("char *", ctx), 0, ffi.sizeof(ctx));
end
function md5(luastr)
local buf = ffi.new("char[33]");
local hash = ffi.new("uint8_t[16]");
local len = #luastr
local p = ffi.cast("const char *", luastr);
local ctx = MD5_CTX();
MD5Init(ctx);
MD5Update(ctx, p, len);
MD5Final(hash, ctx);
bin2str(buf, hash, ffi.sizeof(hash));
return ffi.string(buf);
end