From c18ac52f9e05c742530e5a0e1d7daed6ff64b09f Mon Sep 17 00:00:00 2001 From: starwing Date: Wed, 28 Sep 2011 10:12:36 +0800 Subject: [PATCH 1/4] single md5 dll --- Makefile | 4 +- src/md5.c | 259 +++++++++++++++++++++++++++++++++++++++++++++++- src/md5.def | 2 +- src/md5.h | 5 +- src/md5.lua | 19 ---- src/md5lib.c | 203 ------------------------------------- vc6/md5.def | 2 +- vc6/md5_dll.dsp | 6 +- 8 files changed, 263 insertions(+), 237 deletions(-) delete mode 100755 src/md5.lua delete mode 100755 src/md5lib.c diff --git a/Makefile b/Makefile index 19c95c9..fc9a24f 100755 --- a/Makefile +++ b/Makefile @@ -8,8 +8,7 @@ ifeq "$(LUA_VERSION_NUM)" "500" COMPAT_O= $(COMPAT_DIR)/compat-5.1.o endif -MD5_OBJS= src/md5.o src/md5lib.o $(COMPAT_O) -MD5_LUAS= src/md5.lua +MD5_OBJS= src/md5.o $(COMPAT_O) MD5_LIBNAME = core.so DES56_OBJS= src/des56.o src/ldes56.o @@ -30,7 +29,6 @@ install: src/$(MD5_LIBNAME) src/$(DES56_LIBNAME) mkdir -p $(LUA_LIBDIR)/md5 cp src/$(MD5_LIBNAME) $(LUA_LIBDIR)/md5/core.so mkdir -p $(LUA_DIR) - cp $(MD5_LUAS) $(LUA_DIR) cp src/$(DES56_LIBNAME) $(LUA_LIBDIR) clean: diff --git a/src/md5.c b/src/md5.c index 8b15b43..faec07c 100755 --- a/src/md5.c +++ b/src/md5.c @@ -5,7 +5,18 @@ */ +#include +#include #include +#include + +#include +#include + +#if ! defined (LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 +#include "compat-5.1.h" +#endif + #include "md5.h" @@ -30,7 +41,6 @@ typedef unsigned int WORD32; void md5 (const char *message, long len, char *output); - /* ** Realiza a rotacao no sentido horario dos bits da variavel 'D' do tipo WORD32. ** Os bits sao deslocados de 'num' posicoes @@ -191,7 +201,6 @@ static int converte (WORD32 *x, const char *pt, int num, int old_status) { } - void md5 (const char *message, long len, char *output) { WORD32 d[4]; int status = 0; @@ -212,3 +221,249 @@ void md5 (const char *message, long len, char *output) { word32tobytes(d, output); } + +/** +* Hash function. Returns a hash for a given string. +* @param message: arbitrary binary string. +* @return A 128-bit hash string. +*/ +static int lmd5 (lua_State *L) { + WORD32 d[4]; + int status = 0; + long i = 0; + char buff[HASHSIZE + 16]; /* md5 len \0 */ + size_t len, sl = 0, addlen = 0; + const char *smsg = NULL; + const char *message = luaL_checklstring(L, 1, &len); + if (lua_gettop(L) >= 2) + smsg = luaL_checklstring(L, 2, &sl); + if (!sl) + inic_digest(d); + else if (sscanf(smsg, "%08x%08x%08x%08x %d", + &d[0], &d[1], &d[2], &d[3], &addlen) != 5) + luaL_error(L, "bad md5 state"); + while (status != 2) { + WORD32 d_old[4]; + WORD32 wbuff[16]; + int numbytes = (len-i >= 64) ? 64 : len-i; + if (smsg && numbytes == 0 && len != 0) + break; + /*salva os valores do vetor digest*/ + d_old[0]=d[0]; d_old[1]=d[1]; d_old[2]=d[2]; d_old[3]=d[3]; + status = converte(wbuff, message+i, numbytes, status); + if (status == 2) put_length(wbuff, addlen+len); + digest(wbuff, d); + d[0]+=d_old[0]; d[1]+=d_old[1]; d[2]+=d_old[2]; d[3]+=d_old[3]; + i += numbytes; + } + if (status == 2) { + word32tobytes(d, buff); + lua_pushlstring(L, buff, HASHSIZE); + } + else { + sprintf(buff, "%08x%08x%08x%08x %d", d[0], d[1], d[2], d[3], addlen+len); + lua_pushstring(L, buff); + } + return 1; +} + + +static int tohex(lua_State *L) { + size_t i, l; + const char *str = luaL_checklstring(L, 1, &l); + luaL_Buffer b; + char hex[3] = {}; + luaL_buffinit(L, &b); + for (i = 0; i < l; ++i) { + sprintf(hex, "%02x", str[i] & 0xff); + luaL_addlstring(&b, hex, 2); + } + luaL_pushresult(&b); + return 1; +} + + +static int lmd5hexa(lua_State *L) { + size_t len; + const char *ret = NULL; + int multiret = lmd5(L); + ret = luaL_checklstring(L, -1, &len); + if (len != HASHSIZE) + return multiret; + lua_insert(L, 1); + lua_settop(L, 1); + return tohex(L); +} + + +/** +* X-Or. Does a bit-a-bit exclusive-or of two strings. +* @param s1: arbitrary binary string. +* @param s2: arbitrary binary string with same length as s1. +* @return a binary string with same length as s1 and s2, +* where each bit is the exclusive-or of the corresponding bits in s1-s2. +*/ +static int ex_or (lua_State *L) { + size_t l1, l2; + const char *s1 = luaL_checklstring(L, 1, &l1); + const char *s2 = luaL_checklstring(L, 2, &l2); + luaL_Buffer b; + luaL_argcheck( L, l1 == l2, 2, "lengths must be equal" ); + luaL_buffinit(L, &b); + while (l1--) luaL_putchar(&b, (*s1++)^(*s2++)); + luaL_pushresult(&b); + return 1; +} + + +static void checkseed (lua_State *L) { + if (lua_isnone(L, 3)) { /* no seed? */ + time_t tm = time(NULL); /* for `random' seed */ + lua_pushlstring(L, (char *)&tm, sizeof(tm)); + } +} + + +#define MAXKEY 256 +#define BLOCKSIZE HASHSIZE + + +static int initblock (lua_State *L, const char *seed, int lseed, char *block) { + size_t lkey; + const char *key = luaL_checklstring(L, 2, &lkey); + if (lkey > MAXKEY) + luaL_error(L, "key too long (> %d)", MAXKEY); + memset(block, 0, BLOCKSIZE); + memcpy(block, seed, lseed); + memcpy(block+BLOCKSIZE, key, lkey); + return (int)lkey+BLOCKSIZE; +} + + +static void codestream (lua_State *L, const char *msg, size_t lmsg, + char *block, int lblock) { + luaL_Buffer b; + luaL_buffinit(L, &b); + while (lmsg > 0) { + char code[BLOCKSIZE]; + int i; + md5(block, lblock, code); + for (i=0; i 0; i++, lmsg--) + code[i] ^= *msg++; + luaL_addlstring(&b, code, i); + memcpy(block, code, i); /* update seed */ + } + luaL_pushresult(&b); +} + + +static void decodestream (lua_State *L, const char *cypher, size_t lcypher, + char *block, int lblock) { + luaL_Buffer b; + luaL_buffinit(L, &b); + while (lcypher > 0) { + char code[BLOCKSIZE]; + int i; + md5(block, lblock, code); /* update seed */ + for (i=0; i 0; i++, lcypher--) + code[i] ^= *cypher++; + luaL_addlstring(&b, code, i); + memcpy(block, cypher-i, i); + } + luaL_pushresult(&b); +} + + +/** +* Encrypts a string. Uses the hash function md5 in CFB (Cipher-feedback +* mode). +* @param message: arbitrary binary string to be encrypted. +* @param key: arbitrary binary string to be used as a key. +* @param [seed]: optional arbitrary binary string to be used as a seed. +* if no seed is provided, the function uses the result of +* time() as a seed. +* @return The cyphertext (as a binary string). +*/ +static int crypt (lua_State *L) { + size_t lmsg; + const char *msg = luaL_checklstring(L, 1, &lmsg); + size_t lseed; + const char *seed; + int lblock; + char block[BLOCKSIZE+MAXKEY]; + checkseed(L); + seed = luaL_checklstring(L, 3, &lseed); + if (lseed > BLOCKSIZE) + luaL_error(L, "seed too long (> %d)", BLOCKSIZE); + /* put seed and seed length at the beginning of result */ + block[0] = (char)lseed; + memcpy(block+1, seed, lseed); + lua_pushlstring(L, block, lseed+1); /* to concat with result */ + lblock = initblock(L, seed, lseed, block); + codestream(L, msg, lmsg, block, lblock); + lua_concat(L, 2); + return 1; +} + + +/** +* Decrypts a string. For any message, key, and seed, we have that +* decrypt(crypt(msg, key, seed), key) == msg. +* @param cyphertext: message to be decrypted (this must be the result of + a previous call to crypt. +* @param key: arbitrary binary string to be used as a key. +* @return The plaintext. +*/ +static int decrypt (lua_State *L) { + size_t lcyphertext; + const char *cyphertext = luaL_checklstring(L, 1, &lcyphertext); + size_t lseed = cyphertext[0]; + const char *seed = cyphertext+1; + int lblock; + char block[BLOCKSIZE+MAXKEY]; + luaL_argcheck(L, lcyphertext >= lseed+1 && lseed <= BLOCKSIZE, 1, + "invalid cyphered string"); + cyphertext += lseed+1; + lcyphertext -= lseed+1; + lblock = initblock(L, seed, lseed, block); + decodestream(L, cyphertext, lcyphertext, block, lblock); + return 1; +} + + +/* +** Assumes the table is on top of the stack. +*/ +static void set_info (lua_State *L) { + lua_pushliteral (L, "_COPYRIGHT"); + lua_pushliteral (L, "Copyright (C) 2003 PUC-Rio"); + lua_settable (L, -3); + lua_pushliteral (L, "_DESCRIPTION"); + lua_pushliteral (L, "Basic cryptographic facilities"); + lua_settable (L, -3); + lua_pushliteral (L, "_VERSION"); + lua_pushliteral (L, "MD5 1.1.2"); + lua_settable (L, -3); + lua_pushliteral (L, "HASHSIZE"); + lua_pushinteger (L, HASHSIZE); + lua_settable (L, -3); +} + + +static struct luaL_reg md5lib[] = { + {"sum", lmd5}, + {"sumhexa", lmd5hexa}, + {"tohex", tohex}, + {"exor", ex_or}, + {"crypt", crypt}, + {"decrypt", decrypt}, + {NULL, NULL} +}; + + +LUALIB_API int luaopen_md5 (lua_State *L) { + luaL_openlib(L, "md5", md5lib, 0); + set_info (L); + return 1; +} + diff --git a/src/md5.def b/src/md5.def index 9e072d4..76576c4 100755 --- a/src/md5.def +++ b/src/md5.def @@ -2,4 +2,4 @@ LIBRARY core.dll DESCRIPTION "LuaMD5" VERSION 1.1.2 EXPORTS -luaopen_md5_core +luaopen_md5 diff --git a/src/md5.h b/src/md5.h index 5548bdd..7e2afa2 100755 --- a/src/md5.h +++ b/src/md5.h @@ -8,13 +8,12 @@ #ifndef md5_h #define md5_h -#include - #define HASHSIZE 16 + void md5 (const char *message, long len, char *output); -int luaopen_md5_core (lua_State *L); +LUALIB_API int luaopen_md5 (lua_State *L); #endif diff --git a/src/md5.lua b/src/md5.lua deleted file mode 100755 index 13d22e1..0000000 --- a/src/md5.lua +++ /dev/null @@ -1,19 +0,0 @@ ----------------------------------------------------------------------------- --- $Id: md5.lua,v 1.4 2006/08/21 19:24:21 carregal Exp $ ----------------------------------------------------------------------------- - -local core = require"md5.core" -local string = require"string" - -module ("md5") - ----------------------------------------------------------------------------- --- @param k String with original message. --- @return String with the md5 hash value converted to hexadecimal digits - -function sumhexa (k) - k = core.sum(k) - return (string.gsub(k, ".", function (c) - return string.format("%02x", string.byte(c)) - end)) -end diff --git a/src/md5lib.c b/src/md5lib.c deleted file mode 100755 index af66049..0000000 --- a/src/md5lib.c +++ /dev/null @@ -1,203 +0,0 @@ -/** -* $Id: md5lib.c,v 1.10 2008/05/12 20:51:27 carregal Exp $ -* Cryptographic and Hash functions for Lua -* @author Roberto Ierusalimschy -*/ - - -#include -#include -#include - -#include -#include - -#if ! defined (LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 -#include "compat-5.1.h" -#endif - -#include "md5.h" - - -/** -* Hash function. Returns a hash for a given string. -* @param message: arbitrary binary string. -* @return A 128-bit hash string. -*/ -static int lmd5 (lua_State *L) { - char buff[16]; - size_t l; - const char *message = luaL_checklstring(L, 1, &l); - md5(message, l, buff); - lua_pushlstring(L, buff, 16L); - return 1; -} - - -/** -* X-Or. Does a bit-a-bit exclusive-or of two strings. -* @param s1: arbitrary binary string. -* @param s2: arbitrary binary string with same length as s1. -* @return a binary string with same length as s1 and s2, -* where each bit is the exclusive-or of the corresponding bits in s1-s2. -*/ -static int ex_or (lua_State *L) { - size_t l1, l2; - const char *s1 = luaL_checklstring(L, 1, &l1); - const char *s2 = luaL_checklstring(L, 2, &l2); - luaL_Buffer b; - luaL_argcheck( L, l1 == l2, 2, "lengths must be equal" ); - luaL_buffinit(L, &b); - while (l1--) luaL_putchar(&b, (*s1++)^(*s2++)); - luaL_pushresult(&b); - return 1; -} - - -static void checkseed (lua_State *L) { - if (lua_isnone(L, 3)) { /* no seed? */ - time_t tm = time(NULL); /* for `random' seed */ - lua_pushlstring(L, (char *)&tm, sizeof(tm)); - } -} - - -#define MAXKEY 256 -#define BLOCKSIZE 16 - - - -static int initblock (lua_State *L, const char *seed, int lseed, char *block) { - size_t lkey; - const char *key = luaL_checklstring(L, 2, &lkey); - if (lkey > MAXKEY) - luaL_error(L, "key too long (> %d)", MAXKEY); - memset(block, 0, BLOCKSIZE); - memcpy(block, seed, lseed); - memcpy(block+BLOCKSIZE, key, lkey); - return (int)lkey+BLOCKSIZE; -} - - -static void codestream (lua_State *L, const char *msg, size_t lmsg, - char *block, int lblock) { - luaL_Buffer b; - luaL_buffinit(L, &b); - while (lmsg > 0) { - char code[BLOCKSIZE]; - int i; - md5(block, lblock, code); - for (i=0; i 0; i++, lmsg--) - code[i] ^= *msg++; - luaL_addlstring(&b, code, i); - memcpy(block, code, i); /* update seed */ - } - luaL_pushresult(&b); -} - - -static void decodestream (lua_State *L, const char *cypher, size_t lcypher, - char *block, int lblock) { - luaL_Buffer b; - luaL_buffinit(L, &b); - while (lcypher > 0) { - char code[BLOCKSIZE]; - int i; - md5(block, lblock, code); /* update seed */ - for (i=0; i 0; i++, lcypher--) - code[i] ^= *cypher++; - luaL_addlstring(&b, code, i); - memcpy(block, cypher-i, i); - } - luaL_pushresult(&b); -} - - -/** -* Encrypts a string. Uses the hash function md5 in CFB (Cipher-feedback -* mode). -* @param message: arbitrary binary string to be encrypted. -* @param key: arbitrary binary string to be used as a key. -* @param [seed]: optional arbitrary binary string to be used as a seed. -* if no seed is provided, the function uses the result of -* time() as a seed. -* @return The cyphertext (as a binary string). -*/ -static int crypt (lua_State *L) { - size_t lmsg; - const char *msg = luaL_checklstring(L, 1, &lmsg); - size_t lseed; - const char *seed; - int lblock; - char block[BLOCKSIZE+MAXKEY]; - checkseed(L); - seed = luaL_checklstring(L, 3, &lseed); - if (lseed > BLOCKSIZE) - luaL_error(L, "seed too long (> %d)", BLOCKSIZE); - /* put seed and seed length at the beginning of result */ - block[0] = (char)lseed; - memcpy(block+1, seed, lseed); - lua_pushlstring(L, block, lseed+1); /* to concat with result */ - lblock = initblock(L, seed, lseed, block); - codestream(L, msg, lmsg, block, lblock); - lua_concat(L, 2); - return 1; -} - - -/** -* Decrypts a string. For any message, key, and seed, we have that -* decrypt(crypt(msg, key, seed), key) == msg. -* @param cyphertext: message to be decrypted (this must be the result of - a previous call to crypt. -* @param key: arbitrary binary string to be used as a key. -* @return The plaintext. -*/ -static int decrypt (lua_State *L) { - size_t lcyphertext; - const char *cyphertext = luaL_checklstring(L, 1, &lcyphertext); - size_t lseed = cyphertext[0]; - const char *seed = cyphertext+1; - int lblock; - char block[BLOCKSIZE+MAXKEY]; - luaL_argcheck(L, lcyphertext >= lseed+1 && lseed <= BLOCKSIZE, 1, - "invalid cyphered string"); - cyphertext += lseed+1; - lcyphertext -= lseed+1; - lblock = initblock(L, seed, lseed, block); - decodestream(L, cyphertext, lcyphertext, block, lblock); - return 1; -} - - -/* -** Assumes the table is on top of the stack. -*/ -static void set_info (lua_State *L) { - lua_pushliteral (L, "_COPYRIGHT"); - lua_pushliteral (L, "Copyright (C) 2003 PUC-Rio"); - lua_settable (L, -3); - lua_pushliteral (L, "_DESCRIPTION"); - lua_pushliteral (L, "Basic cryptographic facilities"); - lua_settable (L, -3); - lua_pushliteral (L, "_VERSION"); - lua_pushliteral (L, "MD5 1.1.2"); - lua_settable (L, -3); -} - - -static struct luaL_reg md5lib[] = { - {"sum", lmd5}, - {"exor", ex_or}, - {"crypt", crypt}, - {"decrypt", decrypt}, - {NULL, NULL} -}; - - -int luaopen_md5_core (lua_State *L) { - luaL_openlib(L, "md5", md5lib, 0); - set_info (L); - return 1; -} - diff --git a/vc6/md5.def b/vc6/md5.def index 9ca3553..fc092bd 100755 --- a/vc6/md5.def +++ b/vc6/md5.def @@ -2,4 +2,4 @@ LIBRARY core.dll DESCRIPTION "LuaMD5" VERSION 1.0.1 EXPORTS -luaopen_md5_core +luaopen_md5 diff --git a/vc6/md5_dll.dsp b/vc6/md5_dll.dsp index 202592d..a51d085 100755 --- a/vc6/md5_dll.dsp +++ b/vc6/md5_dll.dsp @@ -53,7 +53,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 lua50.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../bin/vc6/lib/md5/core.dll" /libpath:"../../external-src/lua50/lib/dll" +# ADD LINK32 lua50.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../bin/vc6/lib/md5.dll" /libpath:"../../external-src/lua50/lib/dll" # Begin Special Build Tool SOURCE="$(InputPath)" # End Special Build Tool @@ -105,10 +105,6 @@ SOURCE=..\src\md5.c SOURCE=.\md5.def # End Source File -# Begin Source File - -SOURCE=..\src\md5lib.c -# End Source File # End Group # Begin Group "Header Files" From 505a580ea564f6f4a2610b71eb46262295529bf5 Mon Sep 17 00:00:00 2001 From: starwing Date: Wed, 28 Sep 2011 16:13:32 +0800 Subject: [PATCH 2/4] add lua.h to md5.h --- src/md5.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/md5.h b/src/md5.h index 7e2afa2..9a3d882 100755 --- a/src/md5.h +++ b/src/md5.h @@ -8,9 +8,10 @@ #ifndef md5_h #define md5_h +#include -#define HASHSIZE 16 +#define HASHSIZE 16 void md5 (const char *message, long len, char *output); LUALIB_API int luaopen_md5 (lua_State *L); From 4e642a7164a102428de41926b321a6fae9a70263 Mon Sep 17 00:00:00 2001 From: starwing Date: Mon, 16 Apr 2012 17:10:01 +0800 Subject: [PATCH 3/4] add sumhexa to md5, makes 5.2 compat --- .gitignore | 4 +++ Makefile | 6 ++--- src/ldes56.c | 6 ++++- src/md5.c | 63 ++++++++++++++++++++++++++++++++++++++++------ src/md5.def | 2 +- src/md5.h | 24 ++++++++++++++++-- src/md5.lua | 19 -------------- src/md5lib.c | 66 +++++++++++++++++++++++++++++++++++++++++++------ tests/test.lua | 6 ++--- vc6/md5.def | 2 +- vc6/md5_dll.dsp | 2 +- 11 files changed, 153 insertions(+), 47 deletions(-) create mode 100644 .gitignore delete mode 100755 src/md5.lua diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9776091 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.obj +*.so +*.dll diff --git a/Makefile b/Makefile index 19c95c9..a4f8d7a 100755 --- a/Makefile +++ b/Makefile @@ -9,8 +9,7 @@ COMPAT_O= $(COMPAT_DIR)/compat-5.1.o endif MD5_OBJS= src/md5.o src/md5lib.o $(COMPAT_O) -MD5_LUAS= src/md5.lua -MD5_LIBNAME = core.so +MD5_LIBNAME = md5.so DES56_OBJS= src/des56.o src/ldes56.o DES56_LIBNAME= des56.so @@ -28,9 +27,8 @@ $(COMPAT_DIR)/compat-5.1.o: $(COMPAT_DIR)/compat-5.1.c install: src/$(MD5_LIBNAME) src/$(DES56_LIBNAME) mkdir -p $(LUA_LIBDIR)/md5 - cp src/$(MD5_LIBNAME) $(LUA_LIBDIR)/md5/core.so + cp src/$(MD5_LIBNAME) $(LUA_LIBDIR)/md5.so mkdir -p $(LUA_DIR) - cp $(MD5_LUAS) $(LUA_DIR) cp src/$(DES56_LIBNAME) $(LUA_LIBDIR) clean: diff --git a/src/ldes56.c b/src/ldes56.c index ba365c3..37d5b0f 100755 --- a/src/ldes56.c +++ b/src/ldes56.c @@ -144,7 +144,11 @@ static const struct luaL_Reg des56lib[] = { }; int luaopen_des56 (lua_State *L) { - luaL_openlib (L, "des56", des56lib, 0); +#if LUA_VERSION_NUM < 502 + luaL_register(L, "des56", des56lib); +#elif LUA_VERSION_NUM == 502 + luaL_newlib(L, des56lib); +#endif set_info (L); return 1; } diff --git a/src/md5.c b/src/md5.c index 8b15b43..d15ba1b 100755 --- a/src/md5.c +++ b/src/md5.c @@ -12,12 +12,6 @@ #define WORD 32 #define MASK 0xFFFFFFFF -#if __STDC_VERSION__ >= 199901L -#include -typedef uint32_t WORD32; -#else -typedef unsigned int WORD32; -#endif /** @@ -27,8 +21,31 @@ typedef unsigned int WORD32; * @param output: buffer to receive the hash value. Its size must be * (at least) HASHSIZE. */ -void md5 (const char *message, long len, char *output); +void md5 (const char *message, size_t len, char output[HASHSIZE]); +/** +* init a new md5 calculate context +* @param m a uninitialized md5_t type context +*/ +void md5_init (md5_t *m); + +/** +* update message to md5 context +* @param m a initialized md5_t type context +* @param message aribtary string +* @param len message length +* @return true if update completed, means len is not the multiples of 64. +* false if you can continue update. +*/ +int md5_update (md5_t *m, const char *message, size_t len); + +/** + * finish md5 calculate. + * @param m a md5_type context which previous md5_update on it return true. + * @param output buffer to receive the hash value. its size must be + * (at least) HASHSIZE. + */ +void md5_finish (md5_t *m, char output[HASHSIZE]); /* @@ -192,7 +209,7 @@ static int converte (WORD32 *x, const char *pt, int num, int old_status) { -void md5 (const char *message, long len, char *output) { +void md5 (const char *message, size_t len, char output[HASHSIZE]) { WORD32 d[4]; int status = 0; long i = 0; @@ -212,3 +229,33 @@ void md5 (const char *message, long len, char *output) { word32tobytes(d, output); } +void md5_init(md5_t *m) { + inic_digest(m->d); + m->len = 0; +} + +int md5_update(md5_t *m, const char *message, size_t len) { + WORD32 *d = m->d; + size_t addlen = m->len; + int status = 0, i = 0; + while (status != 2) { + WORD32 d_old[4]; + WORD32 wbuff[16]; + int numbytes = (len-i >= 64) ? 64 : len-i; + if (numbytes == 0 && len != 0) + break; + /*salva os valores do vetor digest*/ + d_old[0]=d[0]; d_old[1]=d[1]; d_old[2]=d[2]; d_old[3]=d[3]; + status = converte(wbuff, message+i, numbytes, status); + if (status == 2) put_length(wbuff, addlen+len); + digest(wbuff, d); + d[0]+=d_old[0]; d[1]+=d_old[1]; d[2]+=d_old[2]; d[3]+=d_old[3]; + i += numbytes; + } + m->len += len; + return status == 2; +} + +void md5_finish (md5_t *m, char output[HASHSIZE]) { + word32tobytes(m->d, output); +} diff --git a/src/md5.def b/src/md5.def index 9e072d4..76576c4 100755 --- a/src/md5.def +++ b/src/md5.def @@ -2,4 +2,4 @@ LIBRARY core.dll DESCRIPTION "LuaMD5" VERSION 1.1.2 EXPORTS -luaopen_md5_core +luaopen_md5 diff --git a/src/md5.h b/src/md5.h index 5548bdd..c7fcaa2 100755 --- a/src/md5.h +++ b/src/md5.h @@ -9,12 +9,32 @@ #define md5_h #include +#include #define HASHSIZE 16 -void md5 (const char *message, long len, char *output); -int luaopen_md5_core (lua_State *L); +#if __STDC_VERSION__ >= 199901L +#include +typedef uint32_t WORD32; +#else +/* static assert that int equal or greater than 32bit. */ +typedef char static_assert_sizeof_int + [sizeof(unsigned int) >= 4 ? 1 : -1]; +typedef unsigned int WORD32; +#endif + +typedef struct md5_t { + WORD32 d[4]; + size_t len; +} md5_t; + +void md5_init (md5_t *m); +int md5_update (md5_t *m, const char *message, size_t len); +void md5_finish (md5_t *m, char output[HASHSIZE]); +void md5 (const char *message, size_t len, char output[HASHSIZE]); + +LUALIB_API int luaopen_md5 (lua_State *L); #endif diff --git a/src/md5.lua b/src/md5.lua deleted file mode 100755 index 13d22e1..0000000 --- a/src/md5.lua +++ /dev/null @@ -1,19 +0,0 @@ ----------------------------------------------------------------------------- --- $Id: md5.lua,v 1.4 2006/08/21 19:24:21 carregal Exp $ ----------------------------------------------------------------------------- - -local core = require"md5.core" -local string = require"string" - -module ("md5") - ----------------------------------------------------------------------------- --- @param k String with original message. --- @return String with the md5 hash value converted to hexadecimal digits - -function sumhexa (k) - k = core.sum(k) - return (string.gsub(k, ".", function (c) - return string.format("%02x", string.byte(c)) - end)) -end diff --git a/src/md5lib.c b/src/md5lib.c index 23b31c7..ff495ec 100755 --- a/src/md5lib.c +++ b/src/md5lib.c @@ -18,22 +18,68 @@ #include "md5.h" +#define MD5_TYPE "md5_t" /** * Hash function. Returns a hash for a given string. * @param message: arbitrary binary string. -* @return A 128-bit hash string. +* @param status: optional hash context +* @return A 128-bit hash string, or a new hash context. */ static int lmd5 (lua_State *L) { + size_t len; + const char *message = luaL_checklstring(L, 1, &len); char buff[16]; - size_t l; - const char *message = luaL_checklstring(L, 1, &l); - md5(message, l, buff); - lua_pushlstring(L, buff, 16L); + if (lua_gettop(L) < 2) { + md5(message, len, buff); + lua_pushlstring(L, buff, 16L); + } + else { + md5_t *m; + lua_settop(L, 2); + if (lua_isuserdata(L, 2)) + m = luaL_checkudata(L, 2, MD5_TYPE); + else { + m = lua_newuserdata(L, sizeof(md5_t)); + luaL_getmetatable(L, MD5_TYPE); + lua_setmetatable(L, -2); + md5_init(m); + } + if (md5_update(m, message, len)) { + md5_finish(m, buff); + lua_pushlstring(L, buff, 16L); + } + } + return 1; +} + + +static int tohex(lua_State *L) { + size_t i, l; + const char *str = luaL_checklstring(L, 1, &l); + luaL_Buffer b; + char hex[3] = {0}; + luaL_buffinit(L, &b); + for (i = 0; i < l; ++i) { + sprintf(hex, "%02x", str[i] & 0xff); + luaL_addlstring(&b, hex, 2); + } + luaL_pushresult(&b); return 1; } +static int lmd5hexa(lua_State *L) { + lmd5(L); + if (!lua_isuserdata(L, -1)) { + lua_insert(L, 1); + lua_settop(L, 1); + return tohex(L); + } + return 1; +} + + /** * X-Or. Does a bit-a-bit exclusive-or of two strings. * @param s1: arbitrary binary string. @@ -188,6 +234,7 @@ static void set_info (lua_State *L) { static struct luaL_Reg md5lib[] = { {"sum", lmd5}, + {"sumhexa", lmd5hexa}, {"exor", ex_or}, {"crypt", crypt}, {"decrypt", decrypt}, @@ -195,8 +242,13 @@ static struct luaL_Reg md5lib[] = { }; -int luaopen_md5_core (lua_State *L) { - luaL_openlib(L, "md5", md5lib, 0); +int luaopen_md5 (lua_State *L) { + luaL_newmetatable(L, MD5_TYPE); +#if LUA_VERSION_NUM < 502 + luaL_register(L, "md5", md5lib); +#elif LUA_VERSION_NUM == 502 + luaL_newlib(L, md5lib); +#endif set_info (L); return 1; } diff --git a/tests/test.lua b/tests/test.lua index 18ce5c7..16a5d8e 100755 --- a/tests/test.lua +++ b/tests/test.lua @@ -2,7 +2,7 @@ -- Testing MD5 -require"md5" +local md5 = require"md5" assert(md5.exor('', '') == '') @@ -82,7 +82,7 @@ print"MD5 OK" -- Testing DES 56 -require 'des56' +local des56 = require 'des56' local key = '&3g4&gs*&3' @@ -107,4 +107,4 @@ assert(des56.decrypt(des56.crypt(ascii, key), key) == ascii) key = string.sub(ascii, 2) assert(des56.decrypt(des56.crypt(ascii, key), key) == ascii) -print"DES56 OK" \ No newline at end of file +print"DES56 OK" diff --git a/vc6/md5.def b/vc6/md5.def index 9ca3553..fc092bd 100755 --- a/vc6/md5.def +++ b/vc6/md5.def @@ -2,4 +2,4 @@ LIBRARY core.dll DESCRIPTION "LuaMD5" VERSION 1.0.1 EXPORTS -luaopen_md5_core +luaopen_md5 diff --git a/vc6/md5_dll.dsp b/vc6/md5_dll.dsp index 202592d..ebe245a 100755 --- a/vc6/md5_dll.dsp +++ b/vc6/md5_dll.dsp @@ -53,7 +53,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 lua50.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../bin/vc6/lib/md5/core.dll" /libpath:"../../external-src/lua50/lib/dll" +# ADD LINK32 lua50.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../bin/vc6/lib/md5.dll" /libpath:"../../external-src/lua50/lib/dll" # Begin Special Build Tool SOURCE="$(InputPath)" # End Special Build Tool From 0eee156f13be1006a1192abf874eac4dc9c34793 Mon Sep 17 00:00:00 2001 From: starwing Date: Tue, 17 Apr 2012 16:10:10 +0800 Subject: [PATCH 4/4] fix md5_update if message < 56 --- src/md5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/md5.c b/src/md5.c index b52b9b3..5b0a8d9 100755 --- a/src/md5.c +++ b/src/md5.c @@ -251,7 +251,7 @@ int md5_update(md5_t *m, const char *message, size_t len) { WORD32 d_old[4]; WORD32 wbuff[16]; int numbytes = (len-i >= 64) ? 64 : len-i; - if (numbytes == 0 && len != 0) + if (status != 1 && numbytes == 0 && len != 0) break; /*salva os valores do vetor digest*/ d_old[0]=d[0]; d_old[1]=d[1]; d_old[2]=d[2]; d_old[3]=d[3];