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