Click here to Skip to main content
15,892,298 members
Articles / Web Development / HTML

My own Mailinator in 5 minutes

Rate me:
Please Sign up or sign in to vote.
5.00/5 (6 votes)
19 Nov 2012CPOL6 min read 31.7K   405   13  
A simple Mailinator clone developed in five minutes with the NetFluid framework
//
// MD4Managed.cs - Message Digest 4 Managed Implementation
//
// Author:
//	Sebastien Pouliot (sebastien@ximian.com)
//
// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
//
// 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.
//

using System;
using System.Security.Cryptography;

namespace LumiSoft.Net { 

    internal abstract class _MD4 : HashAlgorithm {

		protected _MD4 () 
		{
			// MD4 hash length are 128 bits long
			HashSizeValue = 128; 
		}

		public static new _MD4 Create () 
		{
			// for this to work we must register ourself with CryptoConfig
			return Create ("MD4");
		}

		public static new _MD4 Create (string hashName) 
		{
			// in case machine.config isn't configured to use any MD4 implementation
		    return (_MD4) CryptoConfig.CreateFromName (hashName) ?? new MD4Managed ();
		}
	}


	// References:
	// a.     RFC1320: The MD4 Message-Digest Algorithm
	//        http://www.ietf.org/rfc/rfc1320.txt

	internal class MD4Managed : _MD4 {

		private readonly uint[] state;
		private readonly byte[] buffer;
		private readonly uint[] count;
		private readonly uint[] x;

		private const int S11 = 3;
		private const int S12 = 7;
		private const int S13 = 11;
		private const int S14 = 19;
		private const int S21 = 3;
		private const int S22 = 5;
		private const int S23 = 9;
		private const int S24 = 13;
		private const int S31 = 3;
		private const int S32 = 9;
		private const int S33 = 11;
		private const int S34 = 15;

		private readonly byte[] digest;

		//--- constructor -----------------------------------------------------------
                
		public MD4Managed ()
		{
			// we allocate the context memory
			state = new uint [4];
			count = new uint [2];
			buffer = new byte [64];
			digest = new byte [16];
			// temporary buffer in MD4Transform that we don't want to keep allocate on each iteration
			x = new uint [16];
			// the initialize our context
			Initialize ();
		}

		public override void Initialize ()
		{
			count [0] = 0;
			count [1] = 0;
			state [0] = 0x67452301;
			state [1] = 0xefcdab89;
			state [2] = 0x98badcfe;
			state [3] = 0x10325476;
			// Zeroize sensitive information
			Array.Clear (buffer, 0, 64);
			Array.Clear (x, 0, 16);
		}

		protected override void HashCore (byte[] array, int ibStart, int cbSize)
		{
			/* Compute number of bytes mod 64 */
			var index = (int) ((count [0] >> 3) & 0x3F);
			/* Update number of bits */
			count [0] += (uint) (cbSize << 3);
			if (count [0] < (cbSize << 3))
				count [1]++;
			count [1] += (uint) (cbSize >> 29);

			int partLen = 64 - index;
			int i = 0;
			/* Transform as many times as possible. */
			if (cbSize >= partLen) {
				//MD4_memcpy((POINTER)&context->buffer[index], (POINTER)input, partLen);
				Buffer.BlockCopy (array, ibStart, buffer, index, partLen);
				MD4Transform (state, buffer, 0);

				for (i = partLen; i + 63 < cbSize; i += 64) {
					// MD4Transform (context->state, &input[i]);
					MD4Transform (state, array, i);
				}

				index = 0;
			}

			/* Buffer remaining input */
			//MD4_memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i);
			Buffer.BlockCopy (array, ibStart + i, buffer, index, (cbSize-i));
		}

		protected override byte[] HashFinal ()
		{
			/* Save number of bits */
			var bits = new byte [8];
			Encode (bits, count);

			/* Pad out to 56 mod 64. */
			var index = ((count [0] >> 3) & 0x3f);
			var padLen = (int) ((index < 56) ? (56 - index) : (120 - index));
			HashCore (Padding (padLen), 0, padLen);

			/* Append length (before padding) */
			HashCore (bits, 0, 8);

			/* Store state in digest */
			Encode (digest, state);

			// Zeroize sensitive information.
			Initialize ();

			return digest;
		}

		//--- private methods ---------------------------------------------------

		private static byte[] Padding (int nLength) 
		{
			if (nLength > 0) {
				var padding = new byte [nLength];
				padding [0] = 0x80;
				return padding;
			}
			return null;
		}

		/* F, G and H are basic MD4 functions. */
		private static uint F (uint x, uint y, uint z) 
		{
			return ((x) & (y)) | ((~x) & (z));
		}

		private static uint G (uint x, uint y, uint z) 
		{
			return ((x) & (y)) | ((x) & (z)) | ((y) & (z));
		}

		private static uint H (uint x, uint y, uint z) 
		{
			return (x) ^ (y) ^ (z);
		}

		/* ROTATE_LEFT rotates x left n bits. */
		private static uint ROL (uint x, byte n) 
		{
			return ((x) << (n)) | ((x) >> (32-(n)));
		}

		/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
		/* Rotation is separate from addition to prevent recomputation */
		private static void FF (ref uint a, uint b, uint c, uint d, uint x, byte s) 
		{
			a += F (b, c, d) + x;
			a = ROL (a, s);
		}

		private static void GG (ref uint a, uint b, uint c, uint d, uint x, byte s) 
		{
			a += G (b, c, d) + x + 0x5a827999;
			a = ROL (a, s);
		}

		private static void HH (ref uint a, uint b, uint c, uint d, uint x, byte s) 
		{
			a += H (b, c, d) + x + 0x6ed9eba1;
			a = ROL (a, s);
		}

		private static void Encode (byte[] output, uint[] input)
		{
			for (int i = 0, j = 0; j < output.Length; i++, j += 4) {
				output [j]   = (byte)(input [i]);
				output [j+1] = (byte)(input [i] >> 8);
				output [j+2] = (byte)(input [i] >> 16);
				output [j+3] = (byte)(input [i] >> 24);
			}
		}

		private static void Decode (uint[] output, byte[] input, int index) 
		{
			for (int i = 0, j = index; i < output.Length; i++, j += 4) {
				output [i] = (uint) ((input [j]) | (input [j+1] << 8) | (input [j+2] << 16) | (input [j+3] << 24));
			}
		}

		private void MD4Transform (uint[] state, byte[] block, int index)
		{
			uint a = state [0];
			uint b = state [1];
			uint c = state [2];
			uint d = state [3];

			Decode (x, block, index);

			/* Round 1 */
			FF (ref a, b, c, d, x[ 0], S11); /* 1 */
			FF (ref d, a, b, c, x[ 1], S12); /* 2 */
			FF (ref c, d, a, b, x[ 2], S13); /* 3 */
			FF (ref b, c, d, a, x[ 3], S14); /* 4 */
			FF (ref a, b, c, d, x[ 4], S11); /* 5 */
			FF (ref d, a, b, c, x[ 5], S12); /* 6 */
			FF (ref c, d, a, b, x[ 6], S13); /* 7 */
			FF (ref b, c, d, a, x[ 7], S14); /* 8 */
			FF (ref a, b, c, d, x[ 8], S11); /* 9 */
			FF (ref d, a, b, c, x[ 9], S12); /* 10 */
			FF (ref c, d, a, b, x[10], S13); /* 11 */
			FF (ref b, c, d, a, x[11], S14); /* 12 */
			FF (ref a, b, c, d, x[12], S11); /* 13 */
			FF (ref d, a, b, c, x[13], S12); /* 14 */
			FF (ref c, d, a, b, x[14], S13); /* 15 */
			FF (ref b, c, d, a, x[15], S14); /* 16 */

			/* Round 2 */
			GG (ref a, b, c, d, x[ 0], S21); /* 17 */
			GG (ref d, a, b, c, x[ 4], S22); /* 18 */
			GG (ref c, d, a, b, x[ 8], S23); /* 19 */
			GG (ref b, c, d, a, x[12], S24); /* 20 */
			GG (ref a, b, c, d, x[ 1], S21); /* 21 */
			GG (ref d, a, b, c, x[ 5], S22); /* 22 */
			GG (ref c, d, a, b, x[ 9], S23); /* 23 */
			GG (ref b, c, d, a, x[13], S24); /* 24 */
			GG (ref a, b, c, d, x[ 2], S21); /* 25 */
			GG (ref d, a, b, c, x[ 6], S22); /* 26 */
			GG (ref c, d, a, b, x[10], S23); /* 27 */
			GG (ref b, c, d, a, x[14], S24); /* 28 */
			GG (ref a, b, c, d, x[ 3], S21); /* 29 */
			GG (ref d, a, b, c, x[ 7], S22); /* 30 */
			GG (ref c, d, a, b, x[11], S23); /* 31 */
			GG (ref b, c, d, a, x[15], S24); /* 32 */

			HH (ref a, b, c, d, x[ 0], S31); /* 33 */
			HH (ref d, a, b, c, x[ 8], S32); /* 34 */
			HH (ref c, d, a, b, x[ 4], S33); /* 35 */
			HH (ref b, c, d, a, x[12], S34); /* 36 */
			HH (ref a, b, c, d, x[ 2], S31); /* 37 */
			HH (ref d, a, b, c, x[10], S32); /* 38 */
			HH (ref c, d, a, b, x[ 6], S33); /* 39 */
			HH (ref b, c, d, a, x[14], S34); /* 40 */
			HH (ref a, b, c, d, x[ 1], S31); /* 41 */
			HH (ref d, a, b, c, x[ 9], S32); /* 42 */
			HH (ref c, d, a, b, x[ 5], S33); /* 43 */
			HH (ref b, c, d, a, x[13], S34); /* 44 */
			HH (ref a, b, c, d, x[ 3], S31); /* 45 */
			HH (ref d, a, b, c, x[11], S32); /* 46 */
			HH (ref c, d, a, b, x[ 7], S33); /* 47 */
			HH (ref b, c, d, a, x[15], S34); /* 48 */

			state [0] += a;
			state [1] += b;
			state [2] += c;
			state [3] += d;
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer Genny Mobility
Italy Italy
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions