From de2361e72ec68f4ea98f6db2965794b0770a753f Mon Sep 17 00:00:00 2001
From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54>
Date: Tue, 14 Dec 2010 16:25:39 +0000
Subject: [PATCH] plop

git-svn-id: http://svn.net-core.org/repos/t-engine4@2143 51575b47-30f0-44d4-a5cc-537603b46e54
---
 src/luamd5/des56.c  | 548 ++++++++++++++++++++++++++++++++++++++++++++
 src/luamd5/des56.h  |  77 +++++++
 src/luamd5/ldes56.c | 152 ++++++++++++
 src/luamd5/ldes56.h |   1 +
 src/luamd5/md5.c    | 214 +++++++++++++++++
 src/luamd5/md5.h    |  20 ++
 src/luamd5/md5lib.c | 203 ++++++++++++++++
 7 files changed, 1215 insertions(+)
 create mode 100644 src/luamd5/des56.c
 create mode 100644 src/luamd5/des56.h
 create mode 100644 src/luamd5/ldes56.c
 create mode 100644 src/luamd5/ldes56.h
 create mode 100644 src/luamd5/md5.c
 create mode 100644 src/luamd5/md5.h
 create mode 100644 src/luamd5/md5lib.c

diff --git a/src/luamd5/des56.c b/src/luamd5/des56.c
new file mode 100644
index 0000000000..1fb377b906
--- /dev/null
+++ b/src/luamd5/des56.c
@@ -0,0 +1,548 @@
+
+/*
+ * Fast implementation of the DES, as described in the Federal Register,
+ * Vol. 40, No. 52, p. 12134, March 17, 1975.
+ *
+ * Stuart Levy, Minnesota Supercomputer Center, April 1988.
+ * Currently (2007) slevy@ncsa.uiuc.edu
+ * NCSA, University of Illinois Urbana-Champaign
+ *
+ * Calling sequence:
+ *
+ * typedef unsigned long keysched[32];
+ *
+ * fsetkey(key, keysched)	/ * Converts a DES key to a "key schedule" * /
+ *	unsigned char	key[8];
+ *	keysched	*ks;
+ *
+ * fencrypt(block, decrypt, keysched)	/ * En/decrypts one 64-bit block * /
+ *	unsigned char	block[8];	/ * data, en/decrypted in place * /
+ *	int		decrypt;	/ * 0=>encrypt, 1=>decrypt * /
+ *	keysched	*ks;		/ * key schedule, as set by fsetkey * /
+ *
+ * Key and data block representation:
+ * The 56-bit key (bits 1..64 including "parity" bits 8, 16, 24, ..., 64)
+ * and the 64-bit data block (bits 1..64)
+ * are each stored in arrays of 8 bytes.
+ * Following the NBS numbering, the MSB has the bit number 1, so
+ *  key[0] = 128*bit1 + 64*bit2 + ... + 1*bit8, ... through
+ *  key[7] = 128*bit57 + 64*bit58 + ... + 1*bit64.
+ * In the key, "parity" bits are not checked; their values are ignored.
+ *
+*/
+
+/*
+===============================================================================
+License
+
+des56.c is licensed under the terms of the MIT license reproduced below.
+This means that des56.c is free software and can be used for both academic
+and commercial purposes at absolutely no cost.
+===============================================================================
+Copyright (C) 1988 Stuart Levy
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+ */
+
+
+#include "des56.h"
+
+
+/*
+ * Key schedule generation.
+ * We begin by pointlessly permuting the 56 useful key bits into
+ * two groups of 28 bits called C and D.
+ * bK_C and bK_D are indexed by C and D bit numbers, respectively,
+ * and give the key bit number (1..64) which should initialize that C/D bit.
+ * This is the "permuted choice 1" table.
+ */
+
+static tiny bK_C[28] = {
+	57, 49, 41, 33, 25, 17,  9,
+	 1, 58, 50, 42, 34, 26, 18,
+	10,  2, 59, 51, 43, 35, 27,
+	19, 11,  3, 60, 52, 44, 36,
+};
+static tiny bK_D[28] = {
+	63, 55, 47, 39, 31, 23, 15,
+	 7, 62, 54, 46, 38, 30, 22,
+	14,  6, 61, 53, 45, 37, 29,
+	21, 13,  5, 28, 20, 12, 4,
+};
+
+/*
+ * For speed, we invert these, building tables to map groups of
+ * key bits into the corresponding C and D bits.
+ * We represent C and D each as 28 contiguous bits right-justified in a
+ * word, padded on the left with zeros.
+ * If key byte `i' is said to contain bits Ki,0 (MSB) Ki,1 ... Ki,7 (LSB)
+ * then
+ *	wC_K4[i][Ki,0 Ki,1 Ki,2 Ki,3] gives the C bits for Ki,0..3,
+ *	wD_K4[i][Ki,0 Ki,1 Ki,2 Ki,3] the corresponding D bits,
+ *	wC_K3[i][Ki,4 Ki,5 Ki,6] the C bits for Ki,4..6,
+ * and	wD_K3[i][Ki,4 Ki,5 Ki,6] the D bits for Ki,4..6.
+ * Ki,7 is ignored since it is the nominal parity bit.
+ * We could just use a single table for [i][Ki,0 .. Ki,6] but that
+ * would take a lot of storage for such a rarely-used function.
+ */
+
+static	word32 wC_K4[8][16], wC_K3[8][8];
+static	word32 wD_K4[8][16], wD_K3[8][8];
+
+/*
+ * Successive Ci and Di for the sixteen steps in the key schedule are
+ * created by independent 28-bit left circular shifts on C and D.
+ * The shift count varies with the step number.
+ */
+static tiny preshift[16] = {
+	1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1,
+};
+
+/*
+ * Each step in the key schedule is generated by selecting 48 bits
+ * (8 groups of 6 bits) from the appropriately shifted Ci and Di.
+ * bCD_KS, indexed by the key schedule bit number, gives the bit number
+ * in CD (CD1 = MSB of C, CD28 = LSB of C, CD29 = MSB of D, CD56 = LSB of D)
+ * which determines that bit of the key schedule.
+ * Note that only C bits (1..28) appear in the first (upper) 24 bits of
+ * the key schedule, and D bits (29..56) in the second (lower) 24 bits.
+ * This is the "permuted-choice-2" table.
+ */
+
+static tiny bCD_KS[48] = {
+	14, 17, 11, 24,  1,  5,
+	3,  28, 15,  6, 21, 10,
+	23, 19, 12,  4, 26,  8,
+	16,  7, 27, 20, 13,  2,
+	41, 52, 31, 37, 47, 55,
+	30, 40, 51, 45, 33, 48,
+	44, 49, 39, 56, 34, 53,
+	46, 42, 50, 36, 29, 32,
+};
+
+/*
+ * We invert bCD_KS into a pair of tables which map groups of 4
+ * C or D bits into corresponding key schedule bits.
+ * We represent each step of the key schedule as 8 groups of 8 bits,
+ * with the 6 real bits right-justified in each 8-bit group.
+ * hKS_C4[i][C4i+1 .. C4i+4] gives the bits in the high order (first four)
+ * key schedule "bytes" which correspond to C bits 4i+1 .. 4i+4.
+ * lKS_D4[i][D4i+1 .. D4i+4] gives the appropriate bits in the latter (last 4)
+ * key schedule bytes, from the corresponding D bits.
+ */
+
+static word32 hKS_C4[7][16];
+static word32 lKS_D4[7][16];
+
+/*
+ * Encryption/decryption.
+ * Before beginning, and after ending, we perform another useless permutation
+ * on the bits in the data block.
+ *
+ * The initial permutation and its inverse, final permutation
+ * are too simple to need a table for.	If we break the input I1 .. I64 into
+ * 8-bit chunks I0,0 I0,1 ... I0,7 I1,0 I1,1 ... I7,7
+ * then the initial permutation sets LR as follows:
+ * L = I7,1 I6,1 I5,1 ... I0,1	I7,3 I6,3 ... I0,3  I7,5 ... I0,5  I7,7 ... I0,7
+ * and
+ * R = I7,0 I6,0 I5,0 ... I0,0	I7,2 I6,2 ... I0,2  I7,4 ... I0,4  I7,6 ... I0,6
+ *
+ * If we number the bits in the final LR similarly,
+ * L = L0,0 L0,1 ... L3,7  R = R0,0 R0,1 ... R3,7
+ * then the output is
+ * O = R0,7 L0,7 R1,7 L1,7 ... R3,7 L3,7 R0,6 L0,6 ... L3,6 R0,5 ... R3,0 L3,0
+ *
+ * To speed I => LR shuffling we use an array of 32-bit values indexed by
+ * 8-bit input bytes.
+ * wL_I8[ 0 I0,1 0 I0,3 0 I0,5 0 I0,7 ] = the corresponding L bits.
+ * Other R and L bits are derived from wL_I8 by shifting.
+ *
+ * To speed LR => O shuffling, an array of 32-bit values indexed by 4-bit lumps:
+ * wO_L4[ L0,4 L0,5 L0,6 L0,7 ] = the corresponding high-order 32 O bits.
+ */
+
+static word32 wL_I8[0x55 + 1];
+static word32 wO_L4[16];
+
+/*
+ * Core of encryption/decryption.
+ * In each key schedule stage, we:
+ *	take 8 overlapping groups of 6 bits each from R
+ *	   (the NBS tabulates the bit selections in the E table,
+ *	    but it's so simple we just use shifting to get the right bits)
+ *	XOR each group with the corresponding bits from the key schedule
+ *	Use the resulting 6 bits as an index into the appropriate S table
+ *	   (there are 8 such tables, one per group of 6 bits)
+ *	Each S entry yields 4 bits.
+ *	The 8 groups of 4 bits are catenated into a 32-bit value.
+ *	Those 32 bits are permuted according to the P table.
+ *	Finally the permuted 32-bit value is XORed with L and becomes
+ *	the R value for the next stage, while the previous R becomes the new L.
+ *
+ * Here, we merge the P permutation with the S tables by making the
+ * S entries be 32-bit masks, already suitably permuted.
+ * Also, the bits in each six-bit group must be permuted before use as
+ * an index into the NBS-tabulated S tables.
+ * We rearrange entries in wPS so that natural bit order can be used.
+ */
+
+static word32 wPS[8][64];
+
+static tiny P[32] = {
+	16,  7, 20, 21,
+	29, 12, 28, 17,
+	 1, 15, 23, 26,
+	 5, 18, 31, 10,
+	 2,  8, 24, 14,
+	32, 27,  3,  9,
+	19, 13, 30,  6,
+	22, 11,  4, 25,
+};
+
+static tiny S[8][64] = {
+     {
+	14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7,
+	 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8,
+	 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0,
+	15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13,
+     },
+
+     {
+	15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10,
+	 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5,
+	 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15,
+	13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9,
+     },
+
+     {
+	10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8,
+	13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1,
+	13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7,
+	 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12,
+     },
+
+     {
+	 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15,
+	13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9,
+	10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4,
+	 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,
+     },
+
+     {
+	 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9,
+	14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6,
+	 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14,
+	11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3,
+     },
+
+     {
+	12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11,
+	10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8,
+	 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6,
+	 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13,
+     },
+
+     {
+	 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1,
+	13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6,
+	 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2,
+	 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12,
+     },
+
+     {
+	13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7,
+	 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2,
+	 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8,
+	 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11,
+     },
+};
+
+static void buildtables( void )
+{
+	register int i, j;
+	register word32 v;
+	word32 wC_K[64], wD_K[64];
+	word32 hKS_C[28], lKS_D[28];
+	int Smap[64];
+	word32 wP[32];
+
+#if USG
+#  define	ZERO(array)	memset((char *)(array), '\0', sizeof(array))
+#else
+# if BSD
+#  define	ZERO(array)	bzero((char *)(array), sizeof(array))
+# else 
+#  define	ZERO(array)	{ register word32 *p = (word32 *)(array); \
+				  i = sizeof(array) / sizeof(*p); \
+				  do { *p++ = 0; } while(--i > 0); \
+				}
+# endif 
+#endif 
+
+
+	/* Invert permuted-choice-1 (key => C,D) */
+
+	ZERO(wC_K);
+	ZERO(wD_K);
+	v = 1;
+	for(j = 28; --j >= 0; ) {
+		wC_K[ bK_C[j] - 1 ] = wD_K[ bK_D[j] - 1 ] = v;
+		v += v; 	/* (i.e. v <<= 1) */
+	}
+
+	for(i = 0; i < 64; i++) {
+	    int t = 8 >> (i & 3);
+	    for(j = 0; j < 16; j++) {
+		if(j & t) {
+		    wC_K4[i >> 3][j] |= wC_K[i];
+		    wD_K4[i >> 3][j] |= wD_K[i];
+		    if(j < 8) {
+			wC_K3[i >> 3][j] |= wC_K[i + 3];
+			wD_K3[i >> 3][j] |= wD_K[i + 3];
+		    }
+		}
+	    }
+	    /* Generate the sequence 0,1,2,3, 8,9,10,11, ..., 56,57,58,59. */
+	    if(t == 1) i += 4;
+	}
+
+	/* Invert permuted-choice-2 */
+
+	ZERO(hKS_C);
+	ZERO(lKS_D);
+	v = 1;
+	for(i = 24; (i -= 6) >= 0; ) {
+	    j = i+5;
+	    do {
+		hKS_C[ bCD_KS[j] - 1 ] = lKS_D[ bCD_KS[j+24] - 28 - 1 ] = v;
+		v += v; 	/* Like v <<= 1 but may be faster */
+	    } while(--j >= i);
+	    v <<= 2;		/* Keep byte aligned */
+	}
+
+	for(i = 0; i < 28; i++) {
+	    v = 8 >> (i & 3);
+	    for(j = 0; j < 16; j++) {
+		if(j & v) {
+		    hKS_C4[i >> 2][j] |= hKS_C[i];
+		    lKS_D4[i >> 2][j] |= lKS_D[i];
+		}
+	    }
+	}
+
+	/* Initial permutation */
+
+	for(i = 0; i <= 0x55; i++) {
+	    v = 0;
+	    if(i & 64) v =  (word32) 1 << 24;
+	    if(i & 16) v |= (word32) 1 << 16;
+	    if(i & 4)  v |= (word32) 1 << 8;
+	    if(i & 1)  v |= 1;
+	    wL_I8[i] = v;
+	}
+
+	/* Final permutation */
+
+	for(i = 0; i < 16; i++) {
+	    v = 0;
+	    if(i & 1) v = (word32) 1 << 24;
+	    if(i & 2) v |= (word32) 1 << 16;
+	    if(i & 4) v |= (word32) 1 << 8;
+	    if(i & 8) v |= (word32) 1;
+	    wO_L4[i] = v;
+	}
+
+	/* Funny bit rearrangement on second index into S tables */
+
+	for(i = 0; i < 64; i++) {
+		Smap[i] = (i & 0x20) | (i & 1) << 4 | (i & 0x1e) >> 1;
+	}
+
+	/* Invert permutation P into mask indexed by R bit number */
+
+	v = 1;
+	for(i = 32; --i >= 0; ) {
+		wP[ P[i] - 1 ] = v;
+		v += v;
+	}
+
+	/* Build bit-mask versions of S tables, indexed in natural bit order */
+
+	for(i = 0; i < 8; i++) {
+	    for(j = 0; j < 64; j++) {
+		int k, t;
+
+		t = S[i][ Smap[j] ];
+		for(k = 0; k < 4; k++) {
+		    if(t & 8)
+			wPS[i][j] |= wP[4*i + k];
+		    t += t;
+		}
+	    }
+	}
+}
+
+
+void fsetkey(char key[8], keysched *ks)
+{
+	register int i;
+	register word32 C, D;
+	static int built = 0;
+
+	if(!built) {
+		buildtables();
+		built = 1;
+	}
+
+	C = D = 0;
+	for(i = 0; i < 8; i++) {
+		register int v;
+
+		v = key[i] >> 1;	/* Discard "parity" bit */
+		C |= wC_K4[i][(v>>3) & 15] | wC_K3[i][v & 7];
+		D |= wD_K4[i][(v>>3) & 15] | wD_K3[i][v & 7];
+	}
+
+	/*
+	 * C and D now hold the suitably right-justified
+	 * 28 permuted key bits each.
+	 */
+	for(i = 0; i < 16; i++) {
+#ifdef CRAY
+#define choice2(x, v)  x[6][v&15] | x[5][(v>>4)&15] | x[4][(v>>8)&15] | \
+		    x[3][(v>>12)&15] | x[2][(v>>16)&15] | x[1][(v>>20)&15] | \
+		    x[0][(v>>24)&15]
+#else
+		register word32 *ap;
+
+#  define choice2(x, v)  ( \
+		    ap = &(x)[0][0], \
+		    ap[16*6 + (v&15)] | \
+		    ap[16*5 + ((v>>4)&15)]  | ap[16*4 + ((v>>8)&15)]  | \
+		    ap[16*3 + ((v>>12)&15)] | ap[16*2 + ((v>>16)&15)] | \
+		    ap[16*1 + ((v>>20)&15)] | ap[16*0 + ((v>>24)&15)] )
+#endif 
+
+
+		/* 28-bit left circular shift */
+		C <<= preshift[i];
+		C = ((C >> 28) & 3) | (C & (((word32)1<<28) - 1));
+		ks->KS[i].h = choice2(hKS_C4, C);
+
+		D <<= preshift[i];
+		D = ((D >> 28) & 3) | (D & (((word32)1<<28) - 1));
+		ks->KS[i].l = choice2(lKS_D4, D);
+	}
+}
+
+void
+fencrypt(char block[8], int decrypt, keysched *ks)
+{
+	int i;
+	register word32 L, R;
+	register struct keystage *ksp;
+	register word32 *ap;
+
+	/* Initial permutation */
+
+	L = R = 0;
+	i = 7;
+	ap = wL_I8;
+	do {
+		register int v;
+
+		v = block[i];	/* Could optimize according to ENDIAN */
+		L = ap[v & 0x55] | (L << 1);
+		R = ap[(v >> 1) & 0x55] | (R << 1);
+	} while(--i >= 0);
+
+	if(decrypt) {
+		ksp = &ks->KS[15];
+	} else {
+		ksp = &ks->KS[0];
+	}
+
+#ifdef CRAY
+#  define PS(i,j)	wPS[i][j]
+#else 
+#  define PS(i,j)	ap[64*(i) + (j)]
+	ap = &wPS[0][0];
+#endif 
+
+	i = 16;
+	do {
+		register word32 k, tR;
+
+		tR = (R >> 15) | (R << 17);
+
+		k = ksp->h;
+		L ^= PS(0, ((tR >> 12) ^ (k >> 24)) & 63)
+		   | PS(1, ((tR >> 8) ^ (k >> 16)) & 63)
+		   | PS(2, ((tR >> 4) ^ (k >> 8)) & 63)
+		   | PS(3, (tR ^ k) & 63);
+
+		k = ksp->l;
+		L ^= PS(4, ((R >> 11) ^ (k >> 24)) & 63)
+		   | PS(5, ((R >> 7) ^ (k >> 16)) & 63)
+		   | PS(6, ((R >> 3) ^ (k >> 8)) & 63)
+		   | PS(7, ((tR >> 16) ^ k) & 63);
+
+		tR = L;
+		L = R;
+		R = tR;
+
+
+		if(decrypt)
+			ksp--;
+		else
+			ksp++;
+	} while(--i > 0);
+	{
+		register word32 t;
+
+#ifdef CRAY
+# define FP(k)	(wO_L4[ (L >> (k)) & 15 ] << 1 | wO_L4[ (R >> (k)) & 15 ])
+#else 
+# define FP(k)	(ap[ (L >> (k)) & 15 ] << 1 | ap[ (R >> (k)) & 15 ])
+
+		ap = wO_L4;
+#endif 
+
+		t = FP(0) | (FP(8) | (FP(16) | (FP(24) << 2)) << 2) << 2;
+		R = FP(4) | (FP(12) | (FP(20) | (FP(28) << 2)) << 2) << 2;
+		L = t;
+	}
+	{
+		register word32 t;
+		register char *bp;
+
+		bp = &block[7];
+		t = R;
+		*bp = t & 255;
+		*--bp = (t >>= 8) & 255;
+		*--bp = (t >>= 8) & 255;
+		*--bp = (t >> 8) & 255;
+		t = L;
+		*--bp = t & 255;
+		*--bp = (t >>= 8) & 255;
+		*--bp = (t >>= 8) & 255;
+		*--bp = (t >> 8) & 255;
+	}
+}
+
diff --git a/src/luamd5/des56.h b/src/luamd5/des56.h
new file mode 100644
index 0000000000..88e5f137c1
--- /dev/null
+++ b/src/luamd5/des56.h
@@ -0,0 +1,77 @@
+#ifndef DES56_H
+#define DES56_H 1
+/*
+ * Fast implementation of the DES, as described in the Federal Register,
+ * Vol. 40, No. 52, p. 12134, March 17, 1975.
+ *
+ * Stuart Levy, Minnesota Supercomputer Center, April 1988.
+ * Currently (2007) slevy@ncsa.uiuc.edu
+ * NCSA, University of Illinois Urbana-Champaign
+ *
+ * Calling sequence:
+ *
+ * typedef unsigned long keysched[32];
+ *
+ * fsetkey(key, keysched)	/ * Converts a DES key to a "key schedule" * /
+ *	unsigned char	key[8];
+ *	keysched	*ks;
+ *
+ * fencrypt(block, decrypt, keysched)	/ * En/decrypts one 64-bit block * /
+ *	unsigned char	block[8];	/ * data, en/decrypted in place * /
+ *	int		decrypt;	/ * 0=>encrypt, 1=>decrypt * /
+ *	keysched	*ks;		/ * key schedule, as set by fsetkey * /
+ *
+ * Key and data block representation:
+ * The 56-bit key (bits 1..64 including "parity" bits 8, 16, 24, ..., 64)
+ * and the 64-bit data block (bits 1..64)
+ * are each stored in arrays of 8 bytes.
+ * Following the NBS numbering, the MSB has the bit number 1, so
+ *  key[0] = 128*bit1 + 64*bit2 + ... + 1*bit8, ... through
+ *  key[7] = 128*bit57 + 64*bit58 + ... + 1*bit64.
+ * In the key, "parity" bits are not checked; their values are ignored.
+ *
+*/
+
+/*
+===============================================================================
+License
+
+des56.c is licensed under the terms of the MIT license reproduced below.
+This means that des56.c is free software and can be used for both academic
+and commercial purposes at absolutely no cost.
+===============================================================================
+Copyright (C) 1988 Stuart Levy
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+ */
+
+typedef unsigned long word32;
+typedef unsigned char tiny;
+
+typedef struct keysched {
+	struct keystage {
+		word32 h, l;
+	} KS[16];
+} keysched;
+
+extern void fsetkey(char key[8], keysched *ks);
+
+extern void fencrypt(char block[8], int decrypt, keysched *ks);
+
+#endif /*DES56_H*/
diff --git a/src/luamd5/ldes56.c b/src/luamd5/ldes56.c
new file mode 100644
index 0000000000..5b8d9e1efa
--- /dev/null
+++ b/src/luamd5/ldes56.c
@@ -0,0 +1,152 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "des56.h"
+
+#include "lua.h"
+#include "lauxlib.h"
+
+#include "ldes56.h"
+
+static int des56_decrypt( lua_State *L )
+{
+  char* decypheredText;
+  keysched KS;
+  int rel_index, abs_index;
+  size_t cypherlen;
+  const char *cypheredText = 
+    luaL_checklstring( L, 1, &cypherlen );
+  const char *key = luaL_optstring( L, 2, NULL );
+  int padinfo;
+
+  padinfo = cypheredText[cypherlen-1];
+  cypherlen--;
+
+  /* Aloca array */
+  decypheredText = 
+    (char *) malloc( (cypherlen+1) * sizeof(char));
+  if(decypheredText == NULL) {
+    lua_pushstring(L, "Error decrypting file. Not enough memory.");
+    lua_error(L);
+  }
+
+  /* Inicia decifragem */
+  if (key && strlen(key) >= 8)
+  {
+    char k[8];
+    int i;
+
+    for (i=0; i<8; i++)
+      k[i] = (unsigned char)key[i];
+    fsetkey(k, &KS);
+  } else {
+    lua_pushstring(L, "Error decrypting file. Invalid key.");
+    lua_error(L);
+  }
+
+  rel_index = 0;
+  abs_index = 0;
+
+  while (abs_index < (int) cypherlen)
+  {
+    decypheredText[abs_index] = cypheredText[abs_index];
+    abs_index++;
+    rel_index++;
+    if( rel_index == 8 )
+    {
+      rel_index = 0;
+      fencrypt(&(decypheredText[abs_index - 8]), 1, &KS);
+    }
+  }
+  decypheredText[abs_index] = 0;
+
+  lua_pushlstring(L, decypheredText, (abs_index-padinfo));
+  free( decypheredText );
+  return 1;
+}
+
+static int des56_crypt( lua_State *L )
+{
+  char *cypheredText;
+  keysched KS;
+  int rel_index, pad, abs_index;
+  size_t plainlen;
+  const char *plainText = luaL_checklstring( L, 1, &plainlen );
+  const char *key = luaL_optstring( L, 2, NULL );
+
+  cypheredText = (char *) malloc( (plainlen+8) * sizeof(char));
+  if(cypheredText == NULL) {
+    lua_pushstring(L, "Error encrypting file. Not enough memory."); 
+    lua_error(L);
+  }
+
+  if (key && strlen(key) >= 8)
+  {
+    char k[8];
+    int i;
+
+    for (i=0; i<8; i++)
+      k[i] = (unsigned char)key[i];
+    fsetkey(k, &KS);
+  } else {
+    lua_pushstring(L, "Error encrypting file. Invalid key.");
+    lua_error(L);
+  }
+
+  rel_index = 0;
+  abs_index = 0;
+  while (abs_index < (int) plainlen) {
+    cypheredText[abs_index] = plainText[abs_index];
+    abs_index++;
+    rel_index++;
+    if( rel_index == 8 ) {
+      rel_index = 0;
+      fencrypt(&(cypheredText[abs_index - 8]), 0, &KS);
+    }
+  }
+
+  pad = 0;
+  if(rel_index != 0) { /* Pads remaining bytes with zeroes */
+    while(rel_index < 8)
+    {
+      pad++;
+      cypheredText[abs_index++] = 0;
+      rel_index++;
+    }
+    fencrypt(&(cypheredText[abs_index - 8]), 0, &KS);
+  }
+  cypheredText[abs_index] = pad;
+
+  lua_pushlstring( L, cypheredText, abs_index+1 );
+  free( cypheredText );
+  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) 2007 PUC-Rio");
+	lua_settable (L, -3);
+	lua_pushliteral (L, "_DESCRIPTION");
+	lua_pushliteral (L, "DES 56 cryptographic facilities for Lua");
+	lua_settable (L, -3);
+	lua_pushliteral (L, "_VERSION");
+	lua_pushliteral (L, "DES56 1.1.2");
+	lua_settable (L, -3);
+}
+
+static const struct luaL_reg des56lib[] = {
+  {"crypt", des56_crypt},
+  {"decrypt", des56_decrypt},
+  {NULL, NULL},
+};
+
+int luaopen_des56 (lua_State *L) {
+  luaL_openlib (L, "des56", des56lib, 0);
+  set_info (L);
+  return 1;
+}
+
+
diff --git a/src/luamd5/ldes56.h b/src/luamd5/ldes56.h
new file mode 100644
index 0000000000..8c2e86a8ca
--- /dev/null
+++ b/src/luamd5/ldes56.h
@@ -0,0 +1 @@
+int luaopen_des56 (lua_State *L);
diff --git a/src/luamd5/md5.c b/src/luamd5/md5.c
new file mode 100644
index 0000000000..8b15b43763
--- /dev/null
+++ b/src/luamd5/md5.c
@@ -0,0 +1,214 @@
+/**
+*  $Id: md5.c,v 1.2 2008/03/24 20:59:12 mascarenhas Exp $
+*  Hash function MD5
+*  @author  Marcela Ozorio Suarez, Roberto I.
+*/
+
+
+#include <string.h>
+
+#include "md5.h"
+
+
+#define WORD 32
+#define MASK 0xFFFFFFFF
+#if __STDC_VERSION__ >= 199901L
+#include <stdint.h>
+typedef uint32_t WORD32;
+#else
+typedef unsigned int WORD32;
+#endif
+
+
+/**
+*  md5 hash function.
+*  @param message: aribtary string.
+*  @param len: message length.
+*  @param output: buffer to receive the hash value. Its size must be
+*  (at least) HASHSIZE.
+*/
+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
+*/
+#define rotate(D, num)  (D<<num) | (D>>(WORD-num))
+
+/*Macros que definem operacoes relizadas pelo algoritmo  md5 */
+#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~(z))))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~(z))))
+
+
+/*vetor de numeros utilizados pelo algoritmo md5 para embaralhar bits */
+static const WORD32 T[64]={
+                     0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+                     0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+                     0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+                     0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+                     0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+                     0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+                     0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+                     0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+                     0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+                     0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+                     0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+                     0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+                     0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+                     0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+                     0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+                     0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+};
+
+
+static void word32tobytes (const WORD32 *input, char *output) {
+  int j = 0;
+  while (j<4*4) {
+    WORD32 v = *input++;
+    output[j++] = (char)(v & 0xff); v >>= 8;
+    output[j++] = (char)(v & 0xff); v >>= 8;
+    output[j++] = (char)(v & 0xff); v >>= 8;
+    output[j++] = (char)(v & 0xff);
+  }
+}
+
+
+static void inic_digest(WORD32 *d) {
+  d[0] = 0x67452301;
+  d[1] = 0xEFCDAB89;
+  d[2] = 0x98BADCFE;
+  d[3] = 0x10325476;
+}
+
+
+/*funcao que implemeta os quatro passos principais do algoritmo MD5 */
+static void digest(const WORD32 *m, WORD32 *d) {
+  int j;
+  /*MD5 PASSO1 */
+  for (j=0; j<4*4; j+=4) {
+    d[0] = d[0]+ F(d[1], d[2], d[3])+ m[j] + T[j];       d[0]=rotate(d[0], 7);
+    d[0]+=d[1];
+    d[3] = d[3]+ F(d[0], d[1], d[2])+ m[(j)+1] + T[j+1]; d[3]=rotate(d[3], 12);
+    d[3]+=d[0];
+    d[2] = d[2]+ F(d[3], d[0], d[1])+ m[(j)+2] + T[j+2]; d[2]=rotate(d[2], 17);
+    d[2]+=d[3];
+    d[1] = d[1]+ F(d[2], d[3], d[0])+ m[(j)+3] + T[j+3]; d[1]=rotate(d[1], 22);
+    d[1]+=d[2];
+  }
+  /*MD5 PASSO2 */
+  for (j=0; j<4*4; j+=4) {
+    d[0] = d[0]+ G(d[1], d[2], d[3])+ m[(5*j+1)&0x0f] + T[(j-1)+17];
+    d[0] = rotate(d[0],5);
+    d[0]+=d[1];
+    d[3] = d[3]+ G(d[0], d[1], d[2])+ m[((5*(j+1)+1)&0x0f)] + T[(j+0)+17];
+    d[3] = rotate(d[3], 9);
+    d[3]+=d[0];
+    d[2] = d[2]+ G(d[3], d[0], d[1])+ m[((5*(j+2)+1)&0x0f)] + T[(j+1)+17];
+    d[2] = rotate(d[2], 14);
+    d[2]+=d[3];
+    d[1] = d[1]+ G(d[2], d[3], d[0])+ m[((5*(j+3)+1)&0x0f)] + T[(j+2)+17];
+    d[1] = rotate(d[1], 20);
+    d[1]+=d[2];
+  }
+  /*MD5 PASSO3 */
+  for (j=0; j<4*4; j+=4) {
+    d[0] = d[0]+ H(d[1], d[2], d[3])+ m[(3*j+5)&0x0f] + T[(j-1)+33];
+    d[0] = rotate(d[0], 4);
+    d[0]+=d[1];
+    d[3] = d[3]+ H(d[0], d[1], d[2])+ m[(3*(j+1)+5)&0x0f] + T[(j+0)+33];
+    d[3] = rotate(d[3], 11);
+    d[3]+=d[0];
+    d[2] = d[2]+ H(d[3], d[0], d[1])+ m[(3*(j+2)+5)&0x0f] + T[(j+1)+33];
+    d[2] = rotate(d[2], 16);
+    d[2]+=d[3];
+    d[1] = d[1]+ H(d[2], d[3], d[0])+ m[(3*(j+3)+5)&0x0f] + T[(j+2)+33];
+    d[1] = rotate(d[1], 23);
+    d[1]+=d[2];
+  }
+  /*MD5 PASSO4 */
+  for (j=0; j<4*4; j+=4) {
+    d[0] = d[0]+ I(d[1], d[2], d[3])+ m[(7*j)&0x0f] + T[(j-1)+49];
+    d[0] = rotate(d[0], 6);
+    d[0]+=d[1];
+    d[3] = d[3]+ I(d[0], d[1], d[2])+ m[(7*(j+1))&0x0f] + T[(j+0)+49];
+    d[3] = rotate(d[3], 10);
+    d[3]+=d[0];
+    d[2] = d[2]+ I(d[3], d[0], d[1])+ m[(7*(j+2))&0x0f] + T[(j+1)+49];
+    d[2] = rotate(d[2], 15);
+    d[2]+=d[3];
+    d[1] = d[1]+ I(d[2], d[3], d[0])+ m[(7*(j+3))&0x0f] + T[(j+2)+49];
+    d[1] = rotate(d[1], 21);
+    d[1]+=d[2];
+  }
+}
+
+
+static void bytestoword32 (WORD32 *x, const char *pt) {
+  int i;
+  for (i=0; i<16; i++) {
+    int j=i*4;
+    x[i] = (((WORD32)(unsigned char)pt[j+3] << 8 |
+           (WORD32)(unsigned char)pt[j+2]) << 8 |
+           (WORD32)(unsigned char)pt[j+1]) << 8 |
+           (WORD32)(unsigned char)pt[j];
+  }
+
+}
+
+
+static void put_length(WORD32 *x, long len) {
+  /* in bits! */
+  x[14] = (WORD32)((len<<3) & MASK);
+  x[15] = (WORD32)(len>>(32-3) & 0x7);
+}
+
+
+/*
+** returned status:
+*  0 - normal message (full 64 bytes)
+*  1 - enough room for 0x80, but not for message length (two 4-byte words)
+*  2 - enough room for 0x80 plus message length (at least 9 bytes free)
+*/
+static int converte (WORD32 *x, const char *pt, int num, int old_status) {
+  int new_status = 0;
+  char buff[64];
+  if (num<64) {
+    memcpy(buff, pt, num);  /* to avoid changing original string */
+    memset(buff+num, 0, 64-num);
+    if (old_status == 0)
+      buff[num] = '\200';
+    new_status = 1;
+    pt = buff;
+  }
+  bytestoword32(x, pt);
+  if (num <= (64 - 9))
+    new_status = 2;
+  return new_status;
+}
+
+
+
+void md5 (const char *message, long len, char *output) {
+  WORD32 d[4];
+  int status = 0;
+  long i = 0;
+  inic_digest(d);
+  while (status != 2) {
+    WORD32 d_old[4];
+    WORD32 wbuff[16];
+    int numbytes = (len-i >= 64) ? 64 : len-i;
+    /*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, 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;
+  }
+  word32tobytes(d, output);
+}
+
diff --git a/src/luamd5/md5.h b/src/luamd5/md5.h
new file mode 100644
index 0000000000..5548bddadc
--- /dev/null
+++ b/src/luamd5/md5.h
@@ -0,0 +1,20 @@
+/**
+*  $Id: md5.h,v 1.2 2006/03/03 15:04:49 tomas Exp $
+*  Cryptographic module for Lua.
+*  @author  Roberto Ierusalimschy
+*/
+
+
+#ifndef md5_h
+#define md5_h
+
+#include <lua.h>
+
+
+#define HASHSIZE       16
+
+void md5 (const char *message, long len, char *output);
+int luaopen_md5_core (lua_State *L);
+
+
+#endif
diff --git a/src/luamd5/md5lib.c b/src/luamd5/md5lib.c
new file mode 100644
index 0000000000..202903506b
--- /dev/null
+++ b/src/luamd5/md5lib.c
@@ -0,0 +1,203 @@
+/**
+*  $Id: md5lib.c,v 1.10 2008/05/12 20:51:27 carregal Exp $
+*  Cryptographic and Hash functions for Lua
+*  @author  Roberto Ierusalimschy
+*/
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#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<BLOCKSIZE && lmsg > 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<BLOCKSIZE && lcypher > 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
+*  <code>time()</code> 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
+*  <code>decrypt(crypt(msg, key, seed), key) == msg</code>.
+*  @param cyphertext: message to be decrypted (this must be the result of
+   a previous call to <code>crypt</code>.
+*  @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.core", md5lib, 0);
+  set_info (L);
+  return 1;
+}
+
-- 
GitLab