md5lib.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /**
  2. * $Id: md5lib.c,v 1.10 2008/05/12 20:51:27 carregal Exp $
  3. * Cryptographic and Hash functions for Lua
  4. * @author Roberto Ierusalimschy
  5. */
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <time.h>
  9. #include <lua.h>
  10. #include <lauxlib.h>
  11. #include "md5.h"
  12. #include "compat-5.2.h"
  13. /**
  14. * Hash function. Returns a hash for a given string.
  15. * @param message: arbitrary binary string.
  16. * @return A 128-bit hash string.
  17. */
  18. static int lmd5 (lua_State *L) {
  19. char buff[16];
  20. size_t l;
  21. const char *message = luaL_checklstring(L, 1, &l);
  22. md5(message, l, buff);
  23. lua_pushlstring(L, buff, 16L);
  24. return 1;
  25. }
  26. /**
  27. * X-Or. Does a bit-a-bit exclusive-or of two strings.
  28. * @param s1: arbitrary binary string.
  29. * @param s2: arbitrary binary string with same length as s1.
  30. * @return a binary string with same length as s1 and s2,
  31. * where each bit is the exclusive-or of the corresponding bits in s1-s2.
  32. */
  33. static int ex_or (lua_State *L) {
  34. size_t l1, l2;
  35. const char *s1 = luaL_checklstring(L, 1, &l1);
  36. const char *s2 = luaL_checklstring(L, 2, &l2);
  37. luaL_Buffer b;
  38. luaL_argcheck( L, l1 == l2, 2, "lengths must be equal" );
  39. luaL_buffinit(L, &b);
  40. while (l1--) luaL_addchar(&b, (*s1++)^(*s2++));
  41. luaL_pushresult(&b);
  42. return 1;
  43. }
  44. static void checkseed (lua_State *L) {
  45. if (lua_isnone(L, 3)) { /* no seed? */
  46. time_t tm = time(NULL); /* for `random' seed */
  47. lua_pushlstring(L, (char *)&tm, sizeof(tm));
  48. }
  49. }
  50. #define MAXKEY 256
  51. #define BLOCKSIZE 16
  52. static int initblock (lua_State *L, const char *seed, int lseed, char *block) {
  53. size_t lkey;
  54. const char *key = luaL_checklstring(L, 2, &lkey);
  55. if (lkey > MAXKEY)
  56. luaL_error(L, "key too long (> %d)", MAXKEY);
  57. memset(block, 0, BLOCKSIZE);
  58. memcpy(block, seed, lseed);
  59. memcpy(block+BLOCKSIZE, key, lkey);
  60. return (int)lkey+BLOCKSIZE;
  61. }
  62. static void codestream (lua_State *L, const char *msg, size_t lmsg,
  63. char *block, int lblock) {
  64. luaL_Buffer b;
  65. luaL_buffinit(L, &b);
  66. while (lmsg > 0) {
  67. char code[BLOCKSIZE];
  68. int i;
  69. md5(block, lblock, code);
  70. for (i=0; i<BLOCKSIZE && lmsg > 0; i++, lmsg--)
  71. code[i] ^= *msg++;
  72. luaL_addlstring(&b, code, i);
  73. memcpy(block, code, i); /* update seed */
  74. }
  75. luaL_pushresult(&b);
  76. }
  77. static void decodestream (lua_State *L, const char *cypher, size_t lcypher,
  78. char *block, int lblock) {
  79. luaL_Buffer b;
  80. luaL_buffinit(L, &b);
  81. while (lcypher > 0) {
  82. char code[BLOCKSIZE];
  83. int i;
  84. md5(block, lblock, code); /* update seed */
  85. for (i=0; i<BLOCKSIZE && lcypher > 0; i++, lcypher--)
  86. code[i] ^= *cypher++;
  87. luaL_addlstring(&b, code, i);
  88. memcpy(block, cypher-i, i);
  89. }
  90. luaL_pushresult(&b);
  91. }
  92. /**
  93. * Encrypts a string. Uses the hash function md5 in CFB (Cipher-feedback
  94. * mode).
  95. * @param message: arbitrary binary string to be encrypted.
  96. * @param key: arbitrary binary string to be used as a key.
  97. * @param [seed]: optional arbitrary binary string to be used as a seed.
  98. * if no seed is provided, the function uses the result of
  99. * <code>time()</code> as a seed.
  100. * @return The cyphertext (as a binary string).
  101. */
  102. static int crypt (lua_State *L) {
  103. size_t lmsg;
  104. const char *msg = luaL_checklstring(L, 1, &lmsg);
  105. size_t lseed;
  106. const char *seed;
  107. int lblock;
  108. char block[BLOCKSIZE+MAXKEY];
  109. checkseed(L);
  110. seed = luaL_checklstring(L, 3, &lseed);
  111. if (lseed > BLOCKSIZE)
  112. luaL_error(L, "seed too long (> %d)", BLOCKSIZE);
  113. /* put seed and seed length at the beginning of result */
  114. block[0] = (char)lseed;
  115. memcpy(block+1, seed, lseed);
  116. lua_pushlstring(L, block, lseed+1); /* to concat with result */
  117. lblock = initblock(L, seed, lseed, block);
  118. codestream(L, msg, lmsg, block, lblock);
  119. lua_concat(L, 2);
  120. return 1;
  121. }
  122. /**
  123. * Decrypts a string. For any message, key, and seed, we have that
  124. * <code>decrypt(crypt(msg, key, seed), key) == msg</code>.
  125. * @param cyphertext: message to be decrypted (this must be the result of
  126. a previous call to <code>crypt</code>.
  127. * @param key: arbitrary binary string to be used as a key.
  128. * @return The plaintext.
  129. */
  130. static int decrypt (lua_State *L) {
  131. size_t lcyphertext;
  132. const char *cyphertext = luaL_checklstring(L, 1, &lcyphertext);
  133. size_t lseed = cyphertext[0];
  134. const char *seed = cyphertext+1;
  135. int lblock;
  136. char block[BLOCKSIZE+MAXKEY];
  137. luaL_argcheck(L, lcyphertext >= lseed+1 && lseed <= BLOCKSIZE, 1,
  138. "invalid cyphered string");
  139. cyphertext += lseed+1;
  140. lcyphertext -= lseed+1;
  141. lblock = initblock(L, seed, lseed, block);
  142. decodestream(L, cyphertext, lcyphertext, block, lblock);
  143. return 1;
  144. }
  145. /*
  146. ** Assumes the table is on top of the stack.
  147. */
  148. static void set_info (lua_State *L) {
  149. lua_pushliteral (L, "_COPYRIGHT");
  150. lua_pushliteral (L, "Copyright (C) 2003-2013 PUC-Rio");
  151. lua_settable (L, -3);
  152. lua_pushliteral (L, "_DESCRIPTION");
  153. lua_pushliteral (L, "Basic cryptographic facilities");
  154. lua_settable (L, -3);
  155. lua_pushliteral (L, "_VERSION");
  156. lua_pushliteral (L, "MD5 1.2");
  157. lua_settable (L, -3);
  158. }
  159. static struct luaL_Reg md5lib[] = {
  160. {"sum", lmd5},
  161. {"exor", ex_or},
  162. {"crypt", crypt},
  163. {"decrypt", decrypt},
  164. {NULL, NULL}
  165. };
  166. int luaopen_md5_core (lua_State *L) {
  167. lua_newtable(L);
  168. luaL_setfuncs(L, md5lib, 0);
  169. set_info (L);
  170. return 1;
  171. }