Mercurial > projects > dcrypt
annotate dcrypt/crypto/hashes/MD5.d @ 3:a5789a7b3b3b
Fixed error in hash copy() functions where I forgot to copy the length of the message. Now, twice as jank! =)
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Thu, 14 Aug 2008 01:13:26 -0400 |
parents | 71aae178f89a |
children | 5cb17e09d685 |
rev | line source |
---|---|
0 | 1 /** |
2 * This file is part of the dcrypt project. | |
3 * | |
4 * Copyright: Copyright (C) dcrypt contributors 2008. All rights reserved. | |
5 * License: MIT | |
6 * Authors: Thomas Dixon | |
7 */ | |
8 | |
9 module dcrypt.crypto.hashes.MD5; | |
10 | |
11 public import dcrypt.crypto.Hash; | |
12 | |
13 /** Implementation of Ron Rivest's MD5. */ | |
14 class MD5 : Hash { | |
15 private uint h0, h1, h2, h3; | |
16 | |
17 // Shift amounts | |
18 private enum { | |
19 S11 = 7, | |
20 S12 = 12, | |
21 S13 = 17, | |
22 S14 = 22, | |
23 | |
24 S21 = 5, | |
25 S22 = 9, | |
26 S23 = 14, | |
27 S24 = 20, | |
28 | |
29 S31 = 4, | |
30 S32 = 11, | |
31 S33 = 16, | |
32 S34 = 23, | |
33 | |
34 S41 = 6, | |
35 S42 = 10, | |
36 S43 = 15, | |
37 S44 = 21 | |
38 }; | |
39 | |
40 this (void[] input_=null) { | |
41 reset(); | |
42 super(input_); | |
43 } | |
44 | |
45 uint blockSize() { | |
46 return 64; | |
47 } | |
48 | |
49 uint digestSize() { | |
50 return 16; | |
51 } | |
52 | |
53 char[] name() { | |
54 return "MD5"; | |
55 } | |
56 | |
57 void transform(ubyte[] input) { | |
58 uint[] w = new uint[16]; | |
59 | |
60 for (int i = 0, j = 0; i < 16; i++,j+=4) | |
61 w[i] = Util.ubytesToUintLittle(input, j); | |
62 | |
63 uint a = h0, | |
64 b = h1, | |
65 c = h2, | |
66 d = h3; | |
67 | |
68 // Round 1 -- FIGHT! | |
69 ff(a, b, c, d, w[ 0], S11, 3614090360); /* 1 */ | |
70 ff(d, a, b, c, w[ 1], S12, 3905402710); /* 2 */ | |
71 ff(c, d, a, b, w[ 2], S13, 606105819); /* 3 */ | |
72 ff(b, c, d, a, w[ 3], S14, 3250441966); /* 4 */ | |
73 ff(a, b, c, d, w[ 4], S11, 4118548399); /* 5 */ | |
74 ff(d, a, b, c, w[ 5], S12, 1200080426); /* 6 */ | |
75 ff(c, d, a, b, w[ 6], S13, 2821735955); /* 7 */ | |
76 ff(b, c, d, a, w[ 7], S14, 4249261313); /* 8 */ | |
77 ff(a, b, c, d, w[ 8], S11, 1770035416); /* 9 */ | |
78 ff(d, a, b, c, w[ 9], S12, 2336552879); /* 10 */ | |
79 ff(c, d, a, b, w[10], S13, 4294925233); /* 11 */ | |
80 ff(b, c, d, a, w[11], S14, 2304563134); /* 12 */ | |
81 ff(a, b, c, d, w[12], S11, 1804603682); /* 13 */ | |
82 ff(d, a, b, c, w[13], S12, 4254626195); /* 14 */ | |
83 ff(c, d, a, b, w[14], S13, 2792965006); /* 15 */ | |
84 ff(b, c, d, a, w[15], S14, 1236535329); /* 16 */ | |
85 | |
86 // Round 2 | |
87 gg(a, b, c, d, w[ 1], S21, 4129170786); /* 17 */ | |
88 gg(d, a, b, c, w[ 6], S22, 3225465664); /* 18 */ | |
89 gg(c, d, a, b, w[11], S23, 643717713); /* 19 */ | |
90 gg(b, c, d, a, w[ 0], S24, 3921069994); /* 20 */ | |
91 gg(a, b, c, d, w[ 5], S21, 3593408605); /* 21 */ | |
92 gg(d, a, b, c, w[10], S22, 38016083); /* 22 */ | |
93 gg(c, d, a, b, w[15], S23, 3634488961); /* 23 */ | |
94 gg(b, c, d, a, w[ 4], S24, 3889429448); /* 24 */ | |
95 gg(a, b, c, d, w[ 9], S21, 568446438); /* 25 */ | |
96 gg(d, a, b, c, w[14], S22, 3275163606); /* 26 */ | |
97 gg(c, d, a, b, w[ 3], S23, 4107603335); /* 27 */ | |
98 gg(b, c, d, a, w[ 8], S24, 1163531501); /* 28 */ | |
99 gg(a, b, c, d, w[13], S21, 2850285829); /* 29 */ | |
100 gg(d, a, b, c, w[ 2], S22, 4243563512); /* 30 */ | |
101 gg(c, d, a, b, w[ 7], S23, 1735328473); /* 31 */ | |
102 gg(b, c, d, a, w[12], S24, 2368359562); /* 32 */ | |
103 | |
104 // Round 3 | |
105 hh(a, b, c, d, w[ 5], S31, 4294588738); /* 33 */ | |
106 hh(d, a, b, c, w[ 8], S32, 2272392833); /* 34 */ | |
107 hh(c, d, a, b, w[11], S33, 1839030562); /* 35 */ | |
108 hh(b, c, d, a, w[14], S34, 4259657740); /* 36 */ | |
109 hh(a, b, c, d, w[ 1], S31, 2763975236); /* 37 */ | |
110 hh(d, a, b, c, w[ 4], S32, 1272893353); /* 38 */ | |
111 hh(c, d, a, b, w[ 7], S33, 4139469664); /* 39 */ | |
112 hh(b, c, d, a, w[10], S34, 3200236656); /* 40 */ | |
113 hh(a, b, c, d, w[13], S31, 681279174); /* 41 */ | |
114 hh(d, a, b, c, w[ 0], S32, 3936430074); /* 42 */ | |
115 hh(c, d, a, b, w[ 3], S33, 3572445317); /* 43 */ | |
116 hh(b, c, d, a, w[ 6], S34, 76029189); /* 44 */ | |
117 hh(a, b, c, d, w[ 9], S31, 3654602809); /* 45 */ | |
118 hh(d, a, b, c, w[12], S32, 3873151461); /* 46 */ | |
119 hh(c, d, a, b, w[15], S33, 530742520); /* 47 */ | |
120 hh(b, c, d, a, w[ 2], S34, 3299628645); /* 48 */ | |
121 | |
122 // Round 4 | |
123 ii(a, b, c, d, w[ 0], S41, 4096336452); /* 49 */ | |
124 ii(d, a, b, c, w[ 7], S42, 1126891415); /* 50 */ | |
125 ii(c, d, a, b, w[14], S43, 2878612391); /* 51 */ | |
126 ii(b, c, d, a, w[ 5], S44, 4237533241); /* 52 */ | |
127 ii(a, b, c, d, w[12], S41, 1700485571); /* 53 */ | |
128 ii(d, a, b, c, w[ 3], S42, 2399980690); /* 54 */ | |
129 ii(c, d, a, b, w[10], S43, 4293915773); /* 55 */ | |
130 ii(b, c, d, a, w[ 1], S44, 2240044497); /* 56 */ | |
131 ii(a, b, c, d, w[ 8], S41, 1873313359); /* 57 */ | |
132 ii(d, a, b, c, w[15], S42, 4264355552); /* 58 */ | |
133 ii(c, d, a, b, w[ 6], S43, 2734768916); /* 59 */ | |
134 ii(b, c, d, a, w[13], S44, 1309151649); /* 60 */ | |
135 ii(a, b, c, d, w[ 4], S41, 4149444226); /* 61 */ | |
136 ii(d, a, b, c, w[11], S42, 3174756917); /* 62 */ | |
137 ii(c, d, a, b, w[ 2], S43, 718787259); /* 63 */ | |
138 ii(b, c, d, a, w[ 9], S44, 3951481745); /* 64 */ | |
139 | |
140 // FINISH HIM! | |
141 h0 += a; | |
142 h1 += b; | |
143 h2 += c; | |
144 h3 += d; | |
145 // FATALITY! MD5 Wins. \o/ ('cept not because it's insecure, but whatev) | |
146 } | |
147 | |
148 private uint f(uint x, uint y, uint z) { | |
149 return (x&y)|(~x&z); | |
150 } | |
151 | |
152 private uint h(uint x, uint y, uint z) { | |
153 return x^y^z; | |
154 } | |
155 | |
156 private uint g(uint x, uint y, uint z) { | |
157 return (x&z)|(y&~z); | |
158 } | |
159 | |
160 private uint i(uint x, uint y, uint z) { | |
161 return y^(x|~z); | |
162 } | |
163 | |
164 private void ff(ref uint a, uint b, uint c, | |
165 uint d, uint x, uint s, uint ac) { | |
166 a += f(b, c, d) + x + ac; | |
167 a = Util.rotateLeft(a, s); | |
168 a += b; | |
169 } | |
170 | |
171 private void gg(ref uint a, uint b, uint c, | |
172 uint d, uint x, uint s, uint ac) { | |
173 a += g(b, c, d) + x + ac; | |
174 a = Util.rotateLeft(a, s); | |
175 a += b; | |
176 } | |
177 | |
178 private void hh(ref uint a, uint b, uint c, | |
179 uint d, uint x, uint s, uint ac) { | |
180 a += h(b, c, d) + x + ac; | |
181 a = Util.rotateLeft(a, s); | |
182 a += b; | |
183 } | |
184 | |
185 private void ii(ref uint a, uint b, uint c, | |
186 uint d, uint x, uint s, uint ac) { | |
187 a += i(b, c, d) + x + ac; | |
188 a = Util.rotateLeft(a, s); | |
189 a += b; | |
190 } | |
191 | |
192 ubyte[] digest() { | |
193 padMessage(MODE_MD); | |
194 ubyte[] result = new ubyte[digestSize]; | |
195 | |
196 Util.uintToUbytesLittle(h0, result, 0); | |
197 Util.uintToUbytesLittle(h1, result, 4); | |
198 Util.uintToUbytesLittle(h2, result, 8); | |
199 Util.uintToUbytesLittle(h3, result, 12); | |
200 | |
201 reset(); | |
202 return result; | |
203 } | |
204 | |
205 void reset() { | |
206 super.reset(); | |
207 h0 = 0x67452301u, | |
208 h1 = 0xefcdab89u, | |
209 h2 = 0x98badcfeu, | |
210 h3 = 0x10325476u; | |
211 } | |
212 | |
2
71aae178f89a
Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
213 MD5 copy() { |
71aae178f89a
Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
214 MD5 h = new MD5(buffer[0..index]); |
3
a5789a7b3b3b
Fixed error in hash copy() functions where I forgot to copy the length of the message. Now, twice as jank! =)
Thomas Dixon <reikon@reikon.us>
parents:
2
diff
changeset
|
215 h.bytes = bytes; |
2
71aae178f89a
Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
216 h.h0 = h0; |
71aae178f89a
Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
217 h.h1 = h1; |
71aae178f89a
Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
218 h.h2 = h2; |
71aae178f89a
Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
219 h.h3 = h3; |
71aae178f89a
Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
220 return h; |
71aae178f89a
Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
221 } |
71aae178f89a
Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
222 |
0 | 223 version (UnitTest) { |
224 // Found in Tango <3 | |
225 unittest { | |
226 static const char[][] test_inputs = [ | |
227 "", | |
228 "a", | |
229 "abc", | |
230 "message digest", | |
231 "abcdefghijklmnopqrstuvwxyz", | |
232 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", | |
233 "12345678901234567890123456789012345678901234567890123456789012345678901234567890" | |
234 ]; | |
235 | |
236 static const char[][] test_results = [ | |
237 "d41d8cd98f00b204e9800998ecf8427e", | |
238 "0cc175b9c0f1b6a831c399e269772661", | |
239 "900150983cd24fb0d6963f7d28e17f72", | |
240 "f96b697d7cb7938d525a2f31aaf161d0", | |
241 "c3fcd3d76192e4007dfb496cca67e13b", | |
242 "d174ab98d277d9f5a5611c2c9f419d9f", | |
243 "57edf4a22be3c955ac49da2e2107b67a" | |
244 ]; | |
245 | |
246 MD5 h = new MD5(); | |
247 foreach (uint i, char[] input; test_inputs) { | |
248 h.update(input); | |
249 char[] digest = h.hexDigest(); | |
250 assert(digest == test_results[i], | |
2
71aae178f89a
Added copy() to hash functions. Modified some code style.
Thomas Dixon <reikon@reikon.us>
parents:
0
diff
changeset
|
251 h.name~": ("~digest~") != ("~test_results[i]~")"); |
0 | 252 } |
253 } | |
254 } | |
255 } |