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
15
#if ! defined (LUA_VERSION_NUM) || LUA_VERSION_NUM < 501
16
#include "compat-5.1.h"
23
* Hash function. Returns a hash for a given string.
24
* @param message: arbitrary binary string.
25
* @return A 128-bit hash string.
27
static int lmd5 (lua_State *L) {
30
const char *message = luaL_checklstring(L, 1, &l);
31
md5(message, l, buff);
32
lua_pushlstring(L, buff, 16L);
38
* X-Or. Does a bit-a-bit exclusive-or of two strings.
39
* @param s1: arbitrary binary string.
40
* @param s2: arbitrary binary string with same length as s1.
41
* @return a binary string with same length as s1 and s2,
42
* where each bit is the exclusive-or of the corresponding bits in s1-s2.
44
static int ex_or (lua_State *L) {
46
const char *s1 = luaL_checklstring(L, 1, &l1);
47
const char *s2 = luaL_checklstring(L, 2, &l2);
49
luaL_argcheck( L, l1 == l2, 2, "lengths must be equal" );
51
while (l1--) luaL_putchar(&b, (*s1++)^(*s2++));
57
static void checkseed (lua_State *L) {
58
if (lua_isnone(L, 3)) { /* no seed? */
59
time_t tm = time(NULL); /* for `random' seed */
60
lua_pushlstring(L, (char *)&tm, sizeof(tm));
70
static int initblock (lua_State *L, const char *seed, int lseed, char *block) {
72
const char *key = luaL_checklstring(L, 2, &lkey);
74
luaL_error(L, "key too long (> %d)", MAXKEY);
75
memset(block, 0, BLOCKSIZE);
76
memcpy(block, seed, lseed);
77
memcpy(block+BLOCKSIZE, key, lkey);
78
return (int)lkey+BLOCKSIZE;
82
static void codestream (lua_State *L, const char *msg, size_t lmsg,
83
char *block, int lblock) {
89
md5(block, lblock, code);
90
for (i=0; i<BLOCKSIZE && lmsg > 0; i++, lmsg--)
92
luaL_addlstring(&b, code, i);
93
memcpy(block, code, i); /* update seed */
99
static void decodestream (lua_State *L, const char *cypher, size_t lcypher,
100
char *block, int lblock) {
102
luaL_buffinit(L, &b);
103
while (lcypher > 0) {
104
char code[BLOCKSIZE];
106
md5(block, lblock, code); /* update seed */
107
for (i=0; i<BLOCKSIZE && lcypher > 0; i++, lcypher--)
108
code[i] ^= *cypher++;
109
luaL_addlstring(&b, code, i);
110
memcpy(block, cypher-i, i);
117
* Encrypts a string. Uses the hash function md5 in CFB (Cipher-feedback
119
* @param message: arbitrary binary string to be encrypted.
120
* @param key: arbitrary binary string to be used as a key.
121
* @param [seed]: optional arbitrary binary string to be used as a seed.
122
* if no seed is provided, the function uses the result of
123
* <code>time()</code> as a seed.
124
* @return The cyphertext (as a binary string).
126
static int crypt (lua_State *L) {
128
const char *msg = luaL_checklstring(L, 1, &lmsg);
132
char block[BLOCKSIZE+MAXKEY];
134
seed = luaL_checklstring(L, 3, &lseed);
135
if (lseed > BLOCKSIZE)
136
luaL_error(L, "seed too long (> %d)", BLOCKSIZE);
137
/* put seed and seed length at the beginning of result */
138
block[0] = (char)lseed;
139
memcpy(block+1, seed, lseed);
140
lua_pushlstring(L, block, lseed+1); /* to concat with result */
141
lblock = initblock(L, seed, lseed, block);
142
codestream(L, msg, lmsg, block, lblock);
149
* Decrypts a string. For any message, key, and seed, we have that
150
* <code>decrypt(crypt(msg, key, seed), key) == msg</code>.
151
* @param cyphertext: message to be decrypted (this must be the result of
152
a previous call to <code>crypt</code>.
153
* @param key: arbitrary binary string to be used as a key.
154
* @return The plaintext.
156
static int decrypt (lua_State *L) {
158
const char *cyphertext = luaL_checklstring(L, 1, &lcyphertext);
159
size_t lseed = cyphertext[0];
160
const char *seed = cyphertext+1;
162
char block[BLOCKSIZE+MAXKEY];
163
luaL_argcheck(L, lcyphertext >= lseed+1 && lseed <= BLOCKSIZE, 1,
164
"invalid cyphered string");
165
cyphertext += lseed+1;
166
lcyphertext -= lseed+1;
167
lblock = initblock(L, seed, lseed, block);
168
decodestream(L, cyphertext, lcyphertext, block, lblock);
174
** Assumes the table is on top of the stack.
176
static void set_info (lua_State *L) {
177
lua_pushliteral (L, "_COPYRIGHT");
178
lua_pushliteral (L, "Copyright (C) 2003 PUC-Rio");
179
lua_settable (L, -3);
180
lua_pushliteral (L, "_DESCRIPTION");
181
lua_pushliteral (L, "Basic cryptographic facilities");
182
lua_settable (L, -3);
183
lua_pushliteral (L, "_VERSION");
184
lua_pushliteral (L, "MD5 1.1.2");
185
lua_settable (L, -3);
189
static struct luaL_reg md5lib[] = {
193
{"decrypt", decrypt},
198
int luaopen_md5_core (lua_State *L) {
199
luaL_openlib(L, "md5.core", md5lib, 0);