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