comparison tango/tango/io/digest/Md5.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
1 /*******************************************************************************
2
3 copyright: Copyright (c) 2006 Tango. All rights reserved
4
5 license: BSD style: see doc/license.txt for details
6
7 version: Initial release: Feb 2006
8
9 author: Regan Heath, Oskar Linde
10
11 This module implements the MD5 Message Digest Algorithm as described
12 by RFC 1321 The MD5 Message-Digest Algorithm. R. Rivest. April 1992.
13
14 *******************************************************************************/
15
16 module tango.io.digest.Md5;
17
18 public import tango.io.digest.Md4;
19
20 private import tango.io.digest.MerkleDamgard;
21
22 /*******************************************************************************
23
24 *******************************************************************************/
25
26 final class Md5 : Md4
27 {
28 /***********************************************************************
29
30 ***********************************************************************/
31
32 private enum
33 {
34 S11 = 7,
35 S12 = 12,
36 S13 = 17,
37 S14 = 22,
38 S21 = 5,
39 S22 = 9,
40 S23 = 14,
41 S24 = 20,
42 S31 = 4,
43 S32 = 11,
44 S33 = 16,
45 S34 = 23,
46 S41 = 6,
47 S42 = 10,
48 S43 = 15,
49 S44 = 21
50 };
51
52 /***********************************************************************
53
54 Construct an Md5
55
56 ***********************************************************************/
57
58 this() { }
59
60
61 /***********************************************************************
62
63 Performs the cipher on a block of data
64
65 Params:
66 data = the block of data to cipher
67
68 Remarks:
69 The actual cipher algorithm is carried out by this method on
70 the passed block of data. This method is called for every
71 blockSize() bytes of input data and once more with the remaining
72 data padded to blockSize().
73
74 ***********************************************************************/
75
76 protected override void transform(ubyte[] input)
77 {
78 uint a,b,c,d;
79 uint[16] x;
80
81 littleEndian32(input,x);
82
83 a = context[0];
84 b = context[1];
85 c = context[2];
86 d = context[3];
87
88 /* Round 1 */
89 ff(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
90 ff(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
91 ff(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
92 ff(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
93 ff(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
94 ff(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
95 ff(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
96 ff(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
97 ff(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
98 ff(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
99 ff(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
100 ff(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
101 ff(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
102 ff(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
103 ff(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
104 ff(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
105
106 /* Round 2 */
107 gg(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
108 gg(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
109 gg(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
110 gg(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
111 gg(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
112 gg(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
113 gg(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
114 gg(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
115 gg(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
116 gg(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
117 gg(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
118 gg(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
119 gg(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
120 gg(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
121 gg(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
122 gg(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
123
124 /* Round 3 */
125 hh(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
126 hh(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
127 hh(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
128 hh(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
129 hh(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
130 hh(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
131 hh(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
132 hh(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
133 hh(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
134 hh(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
135 hh(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
136 hh(b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
137 hh(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
138 hh(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
139 hh(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
140 hh(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
141
142 /* Round 4 */ /* Md5 not md4 */
143 ii(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
144 ii(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
145 ii(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
146 ii(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
147 ii(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
148 ii(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
149 ii(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
150 ii(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
151 ii(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
152 ii(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
153 ii(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
154 ii(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
155 ii(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
156 ii(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
157 ii(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
158 ii(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
159
160 context[0] += a;
161 context[1] += b;
162 context[2] += c;
163 context[3] += d;
164
165 x[] = 0;
166 }
167
168 /***********************************************************************
169
170 ***********************************************************************/
171
172 private static uint g(uint x, uint y, uint z)
173 {
174 return (x&z)|(y&~z);
175 }
176
177 /***********************************************************************
178
179 ***********************************************************************/
180
181 private static uint i(uint x, uint y, uint z)
182 {
183 return y^(x|~z);
184 }
185
186 /***********************************************************************
187
188 ***********************************************************************/
189
190 private static void ff(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
191 {
192 a += f(b, c, d) + x + ac;
193 a = rotateLeft(a, s);
194 a += b;
195 }
196
197 /***********************************************************************
198
199 ***********************************************************************/
200
201 private static void gg(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
202 {
203 a += g(b, c, d) + x + ac;
204 a = rotateLeft(a, s);
205 a += b;
206 }
207
208 /***********************************************************************
209
210 ***********************************************************************/
211
212 private static void hh(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
213 {
214 a += h(b, c, d) + x + ac;
215 a = rotateLeft(a, s);
216 a += b;
217 }
218
219 /***********************************************************************
220
221 ***********************************************************************/
222
223 private static void ii(inout uint a, uint b, uint c, uint d, uint x, uint s, uint ac)
224 {
225 a += i(b, c, d) + x + ac;
226 a = rotateLeft(a, s);
227 a += b;
228 }
229 }
230
231
232 /*******************************************************************************
233
234 *******************************************************************************/
235
236 version (UnitTest)
237 {
238 unittest
239 {
240 static char[][] strings =
241 [
242 "",
243 "a",
244 "abc",
245 "message digest",
246 "abcdefghijklmnopqrstuvwxyz",
247 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
248 "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
249 ];
250
251 static char[][] results =
252 [
253 "d41d8cd98f00b204e9800998ecf8427e",
254 "0cc175b9c0f1b6a831c399e269772661",
255 "900150983cd24fb0d6963f7d28e17f72",
256 "f96b697d7cb7938d525a2f31aaf161d0",
257 "c3fcd3d76192e4007dfb496cca67e13b",
258 "d174ab98d277d9f5a5611c2c9f419d9f",
259 "57edf4a22be3c955ac49da2e2107b67a"
260 ];
261
262 Md5 h = new Md5();
263
264 foreach (int i, char[] s; strings)
265 {
266 h.update(cast(ubyte[]) s);
267 char[] d = h.hexDigest;
268
269 assert(d == results[i],":("~s~")("~d~")!=("~results[i]~")");
270 }
271 }
272 }