Mercurial > projects > dcrypt
comparison dcrypt/crypto/hashes/MD5.d @ 27:8b5eaf3c2979
Fixed error in hash message padding reported by Glenn Haecker.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Sat, 09 May 2009 23:29:20 -0400 |
parents | 176c933827a8 |
children | ad687db713a4 |
comparison
equal
deleted
inserted
replaced
26:176c933827a8 | 27:8b5eaf3c2979 |
---|---|
15 * | 15 * |
16 * Conforms: RFC 1321 | 16 * Conforms: RFC 1321 |
17 * References: http://www.faqs.org/rfcs/rfc1321.html | 17 * References: http://www.faqs.org/rfcs/rfc1321.html |
18 * Bugs: MD5 is not cryptographically secure. | 18 * Bugs: MD5 is not cryptographically secure. |
19 */ | 19 */ |
20 class MD5 : Hash { | 20 class MD5 : Hash |
21 { | |
21 private uint h0, h1, h2, h3; | 22 private uint h0, h1, h2, h3; |
22 | 23 |
23 // Shift amounts | 24 // Shift amounts |
24 private enum { | 25 private enum |
26 { | |
25 S11 = 7, | 27 S11 = 7, |
26 S12 = 12, | 28 S12 = 12, |
27 S13 = 17, | 29 S13 = 17, |
28 S14 = 22, | 30 S14 = 22, |
29 | 31 |
41 S42 = 10, | 43 S42 = 10, |
42 S43 = 15, | 44 S43 = 15, |
43 S44 = 21 | 45 S44 = 21 |
44 }; | 46 }; |
45 | 47 |
46 this (void[] input_=null) { | 48 this (void[] input_=null) |
49 { | |
47 reset(); | 50 reset(); |
48 super(input_); | 51 super(input_); |
49 } | 52 } |
50 | 53 |
51 uint blockSize() { | 54 uint blockSize() |
55 { | |
52 return 64; | 56 return 64; |
53 } | 57 } |
54 | 58 |
55 uint digestSize() { | 59 uint digestSize() |
60 { | |
56 return 16; | 61 return 16; |
57 } | 62 } |
58 | 63 |
59 char[] name() { | 64 char[] name() |
65 { | |
60 return "MD5"; | 66 return "MD5"; |
61 } | 67 } |
62 | 68 |
63 void transform(ubyte[] input) { | 69 void transform(ubyte[] input) |
70 { | |
64 uint[] w = new uint[16]; | 71 uint[] w = new uint[16]; |
65 | 72 |
66 for (int i = 0, j = 0; i < 16; i++,j+=int.sizeof) | 73 for (int i = 0, j = 0; i < 16; i++,j+=int.sizeof) |
67 w[i] = ByteConverter.LittleEndian.to!(uint)(input[j..j+int.sizeof]); | 74 w[i] = ByteConverter.LittleEndian.to!(uint)(input[j..j+int.sizeof]); |
68 | 75 |
149 h2 += c; | 156 h2 += c; |
150 h3 += d; | 157 h3 += d; |
151 // FATALITY! \o/ | 158 // FATALITY! \o/ |
152 } | 159 } |
153 | 160 |
154 private uint f(uint x, uint y, uint z) { | 161 private uint f(uint x, uint y, uint z) |
162 { | |
155 return (x&y)|(~x&z); | 163 return (x&y)|(~x&z); |
156 } | 164 } |
157 | 165 |
158 private uint h(uint x, uint y, uint z) { | 166 private uint h(uint x, uint y, uint z) |
167 { | |
159 return x^y^z; | 168 return x^y^z; |
160 } | 169 } |
161 | 170 |
162 private uint g(uint x, uint y, uint z) { | 171 private uint g(uint x, uint y, uint z) |
172 { | |
163 return (x&z)|(y&~z); | 173 return (x&z)|(y&~z); |
164 } | 174 } |
165 | 175 |
166 private uint i(uint x, uint y, uint z) { | 176 private uint i(uint x, uint y, uint z) |
177 { | |
167 return y^(x|~z); | 178 return y^(x|~z); |
168 } | 179 } |
169 | 180 |
170 private void ff(ref uint a, uint b, uint c, | 181 private void ff(ref uint a, uint b, uint c, uint d, uint x, uint s, uint ac) |
171 uint d, uint x, uint s, uint ac) { | 182 { |
172 a += f(b, c, d) + x + ac; | 183 a += f(b, c, d) + x + ac; |
173 a = Bitwise.rotateLeft(a, s); | 184 a = Bitwise.rotateLeft(a, s); |
174 a += b; | 185 a += b; |
175 } | 186 } |
176 | 187 |
177 private void gg(ref uint a, uint b, uint c, | 188 private void gg(ref uint a, uint b, uint c, uint d, uint x, uint s, uint ac) |
178 uint d, uint x, uint s, uint ac) { | 189 { |
179 a += g(b, c, d) + x + ac; | 190 a += g(b, c, d) + x + ac; |
180 a = Bitwise.rotateLeft(a, s); | 191 a = Bitwise.rotateLeft(a, s); |
181 a += b; | 192 a += b; |
182 } | 193 } |
183 | 194 |
184 private void hh(ref uint a, uint b, uint c, | 195 private void hh(ref uint a, uint b, uint c, uint d, uint x, uint s, uint ac) |
185 uint d, uint x, uint s, uint ac) { | 196 { |
186 a += h(b, c, d) + x + ac; | 197 a += h(b, c, d) + x + ac; |
187 a = Bitwise.rotateLeft(a, s); | 198 a = Bitwise.rotateLeft(a, s); |
188 a += b; | 199 a += b; |
189 } | 200 } |
190 | 201 |
191 private void ii(ref uint a, uint b, uint c, | 202 private void ii(ref uint a, uint b, uint c, uint d, uint x, uint s, uint ac) |
192 uint d, uint x, uint s, uint ac) { | 203 { |
193 a += i(b, c, d) + x + ac; | 204 a += i(b, c, d) + x + ac; |
194 a = Bitwise.rotateLeft(a, s); | 205 a = Bitwise.rotateLeft(a, s); |
195 a += b; | 206 a += b; |
196 } | 207 } |
197 | 208 |
198 ubyte[] digest() { | 209 ubyte[] digest() |
210 { | |
199 padMessage(MODE_MD); | 211 padMessage(MODE_MD); |
200 ubyte[] result = new ubyte[digestSize]; | 212 ubyte[] result = new ubyte[digestSize]; |
201 | 213 |
202 result[0..4] = ByteConverter.LittleEndian.from!(uint)(h0); | 214 result[0..4] = ByteConverter.LittleEndian.from!(uint)(h0); |
203 result[4..8] = ByteConverter.LittleEndian.from!(uint)(h1); | 215 result[4..8] = ByteConverter.LittleEndian.from!(uint)(h1); |
206 | 218 |
207 reset(); | 219 reset(); |
208 return result; | 220 return result; |
209 } | 221 } |
210 | 222 |
211 void reset() { | 223 void reset() |
224 { | |
212 super.reset(); | 225 super.reset(); |
213 h0 = 0x67452301u; | 226 h0 = 0x67452301u; |
214 h1 = 0xefcdab89u; | 227 h1 = 0xefcdab89u; |
215 h2 = 0x98badcfeu; | 228 h2 = 0x98badcfeu; |
216 h3 = 0x10325476u; | 229 h3 = 0x10325476u; |
217 } | 230 } |
218 | 231 |
219 MD5 copy() { | 232 MD5 copy() |
233 { | |
220 MD5 h = new MD5(buffer[0..index]); | 234 MD5 h = new MD5(buffer[0..index]); |
221 h.bytes = bytes; | 235 h.bytes = bytes; |
222 h.h0 = h0; | 236 h.h0 = h0; |
223 h.h1 = h1; | 237 h.h1 = h1; |
224 h.h2 = h2; | 238 h.h2 = h2; |
225 h.h3 = h3; | 239 h.h3 = h3; |
226 return h; | 240 return h; |
227 } | 241 } |
228 | 242 |
229 debug (UnitTest) { | 243 debug (UnitTest) |
244 { | |
230 // Found in Tango <3 | 245 // Found in Tango <3 |
231 unittest { | 246 unittest |
247 { | |
232 static const char[][] test_inputs = [ | 248 static const char[][] test_inputs = [ |
233 "", | 249 "", |
234 "a", | 250 "a", |
235 "abc", | 251 "abc", |
236 "message digest", | 252 "message digest", |
248 "d174ab98d277d9f5a5611c2c9f419d9f", | 264 "d174ab98d277d9f5a5611c2c9f419d9f", |
249 "57edf4a22be3c955ac49da2e2107b67a" | 265 "57edf4a22be3c955ac49da2e2107b67a" |
250 ]; | 266 ]; |
251 | 267 |
252 MD5 h = new MD5(); | 268 MD5 h = new MD5(); |
253 foreach (uint i, char[] input; test_inputs) { | 269 foreach (uint i, char[] input; test_inputs) |
270 { | |
254 h.update(input); | 271 h.update(input); |
255 char[] digest = h.hexDigest(); | 272 char[] digest = h.hexDigest(); |
256 assert(digest == test_results[i], | 273 assert(digest == test_results[i], |
257 h.name~": ("~digest~") != ("~test_results[i]~")"); | 274 h.name~": ("~digest~") != ("~test_results[i]~")"); |
258 } | 275 } |