PageRenderTime 63ms CodeModel.GetById 45ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/hashes/md5.d

http://github.com/wilkie/djehuty
D | 172 lines | 115 code | 34 blank | 23 comment | 9 complexity | ca6be0321f885b96ebb8ef6ba457b7a3 MD5 | raw file
  1/*
  2 * md5.d
  3 *
  4 * This module implements the MD5 digest.
  5 *
  6 * Author: Dave Wilkinson, Lindsey Bieda
  7 * Originated: January 13th, 2009
  8 *
  9 */
 10
 11module hashes.md5;
 12
 13import core.stream;
 14import core.endian;
 15import core.string;
 16import core.unicode;
 17import core.definitions;
 18
 19import hashes.digest;
 20
 21// Description: This class will compute a hash using the MD5 algorithm.
 22class HashMD5 {
 23private:
 24
 25	static uint r[64] = [	7, 12, 17, 22, 7, 12, 17, 22,
 26							7, 12, 17, 22, 7, 12, 17, 22,
 27							5, 9, 14, 20, 5, 9, 14, 20,
 28							5, 9, 14, 20, 5, 9, 14, 20,
 29							4, 11, 16, 23, 4, 11, 16, 23,
 30							4, 11, 16, 23, 4, 11, 16, 23,
 31							6, 10, 15, 21, 6, 10, 15, 21,
 32							6, 10, 15, 21, 6, 10, 15, 21	];
 33
 34	static uint k[64] = [	0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
 35							0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
 36							0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
 37							0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
 38							0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
 39							0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
 40							0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
 41							0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
 42							0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
 43							0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
 44							0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
 45							0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
 46							0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
 47							0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
 48							0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
 49							0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391	];
 50
 51	static uint g[64] = [	0, 1, 2, 3, 4, 5, 6, 7,
 52							8, 9, 10, 11, 12, 13, 14, 15,
 53							1, 6, 11, 0, 5, 10, 15, 4,
 54							9, 14, 3, 8, 13, 2, 7, 12,
 55							5, 8, 11, 14, 1, 4, 7, 10,
 56							13, 0, 3, 6, 9, 12, 15, 2,
 57							0, 7, 14, 5, 12, 3, 10, 1,
 58							8, 15, 6, 13, 4, 11, 2, 9 ];
 59
 60static:
 61public:
 62
 63	Digest hash(ubyte[] byteArray) {
 64		int len = byteArray.length;
 65
 66	    int bufferLen = (((len+9)/64)+1)*64, i;
 67	    ubyte[] buffer;
 68
 69	    long bitLen = len*8;
 70
 71	    ubyte* bufferptr;
 72
 73	    int* data;
 74	    int* dataEnd;
 75
 76	    uint a, b, c, d, tmp;
 77
 78	    uint a0 = FromBigEndian32(0x01234567);
 79		uint b0 = FromBigEndian32(0x89ABCDEF);
 80		uint c0 = FromBigEndian32(0xFEDCBA98);
 81		uint d0 = FromBigEndian32(0x76543210);
 82
 83	    buffer = new ubyte[bufferLen];
 84
 85	    // initialize buffer
 86	    buffer[0..len] = byteArray[0..len];
 87	    buffer[len] = 0x80;
 88		// NOTE: buffer[len+1..bufferLen-8] = 0;
 89
 90		// set the initial point in the buffer to use
 91	    bufferptr = &buffer[bufferLen-8];
 92
 93	    ubyte* bufferEnd = (&buffer[0]) + bufferLen;
 94
 95	    while(bufferptr != bufferEnd) {
 96	        *bufferptr = cast(ubyte)(bitLen);
 97
 98	        bufferptr++;
 99	        bitLen = bitLen >> 8;
100	    }
101
102	    data = cast(int*)buffer;
103	    dataEnd = cast(int*)bufferEnd;
104
105		// encode the data
106	    while(data != dataEnd) {
107	        a = a0;
108	        b = b0;
109	        c = c0;
110	        d = d0;
111
112	        for(i=0; i<64; i++) {
113	            if(i<16) {
114	                a += (b & c) | (~b & d);
115	            }
116	            else if(i<32) {
117	                a += (b & d) | (~d & c);
118	            }
119	            else if(i<48) {
120	                a += (b ^ c ^ d);
121	            }
122	            else {
123	                a += c ^ (~d | b);
124	            }
125
126	            a += data[g[i]] + k[i];
127	            a = (a << r[i]) | (a >> 32-r[i]);
128	            a+= b;
129
130	            tmp = d;
131	            d = c;
132	            c = b;
133	            b = a;
134	            a = tmp;
135	        }
136
137	        a0 += a;
138	        b0 += b;
139	        c0 += c;
140	        d0 += d;
141
142	        data+=16;
143	    }
144
145		// the final rotations (go back to big endian)
146		a = NativeToBE32(a0);
147		b = NativeToBE32(b0);
148		c = NativeToBE32(c0);
149		d = NativeToBE32(d0);
150
151		// form the hash
152
153		// need formatted constructor
154		return new Digest(a,b,c,d);
155	}
156
157	// Description: This function will calculate the MD5 hash of a stream.
158	// stream: The stream to digest.
159	// Returns: A String representing the MD5 hash.
160	Digest hash(Stream stream) {
161		return hash(stream.contents());
162	}
163
164	// Description: This function will calculate the MD5 hash of a UTF8 encoded string.
165	// utf8Message: The string to hash.
166	// Returns: A string representing the MD5 hash.
167	Digest hash(string utfMessage) {
168		return hash(cast(ubyte[])utfMessage);
169	}
170
171	alias hash opCall;
172}