beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luamd5 / md5lib.c
blob40fd2de386b7286f04dd54f14e55e52d00a78a72
1 /**
2 * $Id: md5lib.c,v 1.2 2003/04/28 16:25:44 roberto Exp $
3 * Cryptographic and Hash functions for Lua
4 * @version 1.0
5 * @author Roberto Ierusalimschy
6 */
9 #include <stdlib.h>
10 #include <string.h>
11 #include <time.h>
13 #include <lua.h>
14 #include <lauxlib.h>
16 #include "luamd5.h"
19 /**
20 * Hash function. Returns a hash for a given string.
21 * @param message: arbitrary binary string.
22 * @return A 128-bit hash string.
24 static int lmd5 (lua_State *L) {
25 char buff[16];
26 size_t l;
27 const char *message = luaL_checklstring(L, 1, &l);
28 md5(message, l, buff);
29 lua_pushlstring(L, buff, 16L);
30 return 1;
34 /**
35 * X-Or. Does a bit-a-bit exclusive-or of two strings.
36 * @param s1: arbitrary binary string.
37 * @param s2: arbitrary binary string with same length as s1.
38 * @return a binary string with same length as s1 and s2,
39 * where each bit is the exclusive-or of the corresponding bits in s1-s2.
41 static int ex_or (lua_State *L) {
42 size_t l1, l2;
43 const char *s1 = luaL_checklstring(L, 1, &l1);
44 const char *s2 = luaL_checklstring(L, 2, &l2);
45 luaL_Buffer b;
46 luaL_argcheck( L, l1 == l2, 2, "lengths must be equal" );
47 luaL_buffinit(L, &b);
48 while (l1--) luaL_addchar(&b, (*s1++)^(*s2++));
49 luaL_pushresult(&b);
50 return 1;
54 static void checkseed (lua_State *L) {
55 if (lua_isnone(L, 3)) { /* no seed? */
56 time_t tm = time(NULL); /* for `random' seed */
57 lua_pushlstring(L, (char *)&tm, sizeof(tm));
62 #define MAXKEY 256
63 #define BLOCKSIZE 16
67 static int initblock (lua_State *L, const char *seed, int lseed, char *block) {
68 size_t lkey;
69 const char *key = luaL_checklstring(L, 2, &lkey);
70 if (lkey > MAXKEY)
71 luaL_error(L, "key too long (> %d)", MAXKEY);
72 memset(block, 0, BLOCKSIZE);
73 memcpy(block, seed, lseed);
74 memcpy(block+BLOCKSIZE, key, lkey);
75 return (int)lkey+BLOCKSIZE;
79 static void codestream (lua_State *L, const char *msg, size_t lmsg,
80 char *block, int lblock) {
81 luaL_Buffer b;
82 luaL_buffinit(L, &b);
83 while (lmsg > 0) {
84 char code[BLOCKSIZE];
85 int i;
86 md5(block, lblock, code);
87 for (i=0; i<BLOCKSIZE && lmsg > 0; i++, lmsg--)
88 code[i] ^= *msg++;
89 luaL_addlstring(&b, code, i);
90 memcpy(block, code, i); /* update seed */
92 luaL_pushresult(&b);
96 static void decodestream (lua_State *L, const char *cypher, size_t lcypher,
97 char *block, int lblock) {
98 luaL_Buffer b;
99 luaL_buffinit(L, &b);
100 while (lcypher > 0) {
101 char code[BLOCKSIZE];
102 int i;
103 md5(block, lblock, code); /* update seed */
104 for (i=0; i<BLOCKSIZE && lcypher > 0; i++, lcypher--)
105 code[i] ^= *cypher++;
106 luaL_addlstring(&b, code, i);
107 memcpy(block, cypher-i, i);
109 luaL_pushresult(&b);
114 * Encrypts a string. Uses the hash function md5 in CFB (Cipher-feedback
115 * mode).
116 * @param message: arbitrary binary string to be encrypted.
117 * @param key: arbitrary binary string to be used as a key.
118 * @param [seed]: optional arbitrary binary string to be used as a seed.
119 * if no seed is provided, the function uses the result of
120 * <code>time()</code> as a seed.
121 * @return The cyphertext (as a binary string).
123 static int crypt (lua_State *L) {
124 size_t lmsg;
125 const char *msg = luaL_checklstring(L, 1, &lmsg);
126 size_t lseed;
127 const char *seed;
128 int lblock;
129 char block[BLOCKSIZE+MAXKEY];
130 checkseed(L);
131 seed = luaL_checklstring(L, 3, &lseed);
132 if (lseed > BLOCKSIZE)
133 luaL_error(L, "seed too long (> %d)", BLOCKSIZE);
134 /* put seed and seed length at the beginning of result */
135 block[0] = (char)lseed;
136 memcpy(block+1, seed, lseed);
137 lua_pushlstring(L, block, lseed+1); /* to concat with result */
138 lblock = initblock(L, seed, lseed, block);
139 codestream(L, msg, lmsg, block, lblock);
140 lua_concat(L, 2);
141 return 1;
146 * Decrypts a string. For any message, key, and seed, we have that
147 * <code>decrypt(crypt(msg, key, seed), key) == msg</code>.
148 * @param cyphertext: message to be decrypted (this must be the result of
149 a previous call to <code>crypt</code>.
150 * @param key: arbitrary binary string to be used as a key.
151 * @return The plaintext.
153 static int decrypt (lua_State *L) {
154 size_t lcyphertext;
155 const char *cyphertext = luaL_checklstring(L, 1, &lcyphertext);
156 size_t lseed = cyphertext[0];
157 const char *seed = cyphertext+1;
158 int lblock;
159 char block[BLOCKSIZE+MAXKEY];
160 luaL_argcheck(L, lcyphertext >= lseed+1 && lseed <= BLOCKSIZE, 1,
161 "invalid cyphered string");
162 cyphertext += lseed+1;
163 lcyphertext -= lseed+1;
164 lblock = initblock(L, seed, lseed, block);
165 decodestream(L, cyphertext, lcyphertext, block, lblock);
166 return 1;
170 static struct luaL_Reg md5lib[] = {
171 {"sum", lmd5},
172 {"exor", ex_or},
173 {"crypt", crypt},
174 {"decrypt", decrypt},
175 {NULL, NULL}
179 int luaopen_md5 (lua_State *L) {
180 luaL_openlib(L, "md5", md5lib, 0);
181 return 1;