comparison dcrypt/crypto/hashes/MD4.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 1320 16 * Conforms: RFC 1320
17 * References: http://www.faqs.org/rfcs/rfc1320.html 17 * References: http://www.faqs.org/rfcs/rfc1320.html
18 * Bugs: MD4 is not cryptographically secure. 18 * Bugs: MD4 is not cryptographically secure.
19 */ 19 */
20 class MD4 : Hash { 20 class MD4 : 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 = 3, 27 S11 = 3,
26 S12 = 7, 28 S12 = 7,
27 S13 = 11, 29 S13 = 11,
28 S14 = 19, 30 S14 = 19,
29 31
36 S32 = 9, 38 S32 = 9,
37 S33 = 11, 39 S33 = 11,
38 S34 = 15 40 S34 = 15
39 }; 41 };
40 42
41 this (void[] input_=null) { 43 this (void[] input_=null)
44 {
42 reset(); 45 reset();
43 super(input_); 46 super(input_);
44 } 47 }
45 48
46 uint blockSize() { 49 uint blockSize()
50 {
47 return 64; 51 return 64;
48 } 52 }
49 53
50 uint digestSize() { 54 uint digestSize()
55 {
51 return 16; 56 return 16;
52 } 57 }
53 58
54 char[] name() { 59 char[] name()
60 {
55 return "MD4"; 61 return "MD4";
56 } 62 }
57 63
58 void transform(ubyte[] input) { 64 void transform(ubyte[] input)
65 {
59 uint[] w = new uint[16]; 66 uint[] w = new uint[16];
60 67
61 for (int i = 0, j = 0; i < 16; i++,j+=int.sizeof) 68 for (int i = 0, j = 0; i < 16; i++,j+=int.sizeof)
62 w[i] = ByteConverter.LittleEndian.to!(uint)(input[j..j+int.sizeof]); 69 w[i] = ByteConverter.LittleEndian.to!(uint)(input[j..j+int.sizeof]);
63 70
124 h1 += b; 131 h1 += b;
125 h2 += c; 132 h2 += c;
126 h3 += d; 133 h3 += d;
127 } 134 }
128 135
129 private uint f(uint x, uint y, uint z) { 136 private uint f(uint x, uint y, uint z)
137 {
130 return (x&y)|(~x&z); 138 return (x&y)|(~x&z);
131 } 139 }
132 140
133 private uint h(uint x, uint y, uint z) { 141 private uint h(uint x, uint y, uint z)
142 {
134 return x^y^z; 143 return x^y^z;
135 } 144 }
136 145
137 private uint g(uint x, uint y, uint z) { 146 private uint g(uint x, uint y, uint z)
147 {
138 return (x&y)|(x&z)|(y&z); 148 return (x&y)|(x&z)|(y&z);
139 } 149 }
140 150
141 private void ff(ref uint a, uint b, uint c, uint d, uint x, uint s) { 151 private void ff(ref uint a, uint b, uint c, uint d, uint x, uint s)
152 {
142 a += f(b, c, d) + x; 153 a += f(b, c, d) + x;
143 a = Bitwise.rotateLeft(a, s); 154 a = Bitwise.rotateLeft(a, s);
144 } 155 }
145 156
146 private void gg(ref uint a, uint b, uint c, uint d, uint x, uint s) { 157 private void gg(ref uint a, uint b, uint c, uint d, uint x, uint s)
158 {
147 a += g(b, c, d) + x + 0x5a827999u; 159 a += g(b, c, d) + x + 0x5a827999u;
148 a = Bitwise.rotateLeft(a, s); 160 a = Bitwise.rotateLeft(a, s);
149 } 161 }
150 162
151 private void hh(ref uint a, uint b, uint c, uint d, uint x, uint s) { 163 private void hh(ref uint a, uint b, uint c, uint d, uint x, uint s)
164 {
152 a += h(b, c, d) + x + 0x6ed9eba1u; 165 a += h(b, c, d) + x + 0x6ed9eba1u;
153 a = Bitwise.rotateLeft(a, s); 166 a = Bitwise.rotateLeft(a, s);
154 } 167 }
155 168
156 ubyte[] digest() { 169 ubyte[] digest()
170 {
157 padMessage(MODE_MD); 171 padMessage(MODE_MD);
158 ubyte[] result = new ubyte[digestSize]; 172 ubyte[] result = new ubyte[digestSize];
159 173
160 result[0..4] = ByteConverter.LittleEndian.from!(uint)(h0); 174 result[0..4] = ByteConverter.LittleEndian.from!(uint)(h0);
161 result[4..8] = ByteConverter.LittleEndian.from!(uint)(h1); 175 result[4..8] = ByteConverter.LittleEndian.from!(uint)(h1);
164 178
165 reset(); 179 reset();
166 return result; 180 return result;
167 } 181 }
168 182
169 void reset() { 183 void reset()
184 {
170 super.reset(); 185 super.reset();
171 h0 = 0x67452301u; 186 h0 = 0x67452301u;
172 h1 = 0xefcdab89u; 187 h1 = 0xefcdab89u;
173 h2 = 0x98badcfeu; 188 h2 = 0x98badcfeu;
174 h3 = 0x10325476u; 189 h3 = 0x10325476u;
175 } 190 }
176 191
177 MD4 copy() { 192 MD4 copy()
193 {
178 MD4 h = new MD4(buffer[0..index]); 194 MD4 h = new MD4(buffer[0..index]);
179 h.bytes = bytes; 195 h.bytes = bytes;
180 h.h0 = h0; 196 h.h0 = h0;
181 h.h1 = h1; 197 h.h1 = h1;
182 h.h2 = h2; 198 h.h2 = h2;
183 h.h3 = h3; 199 h.h3 = h3;
184 return h; 200 return h;
185 } 201 }
186 202
187 debug (UnitTest) { 203 debug (UnitTest)
204 {
188 // Found in Tango <3 205 // Found in Tango <3
189 unittest { 206 unittest
207 {
190 static const char[][] test_inputs = [ 208 static const char[][] test_inputs = [
191 "", 209 "",
192 "a", 210 "a",
193 "abc", 211 "abc",
194 "message digest", 212 "message digest",
206 "043f8582f241db351ce627e153e7f0e4", 224 "043f8582f241db351ce627e153e7f0e4",
207 "e33b4ddc9c38f2199c3e7b164fcc0536" 225 "e33b4ddc9c38f2199c3e7b164fcc0536"
208 ]; 226 ];
209 227
210 MD4 h = new MD4(); 228 MD4 h = new MD4();
211 foreach (uint i, char[] input; test_inputs) { 229 foreach (uint i, char[] input; test_inputs)
230 {
212 h.update(input); 231 h.update(input);
213 char[] digest = h.hexDigest(); 232 char[] digest = h.hexDigest();
214 assert(digest == test_results[i], 233 assert(digest == test_results[i],
215 h.name~": ("~digest~") != ("~test_results[i]~")"); 234 h.name~": ("~digest~") != ("~test_results[i]~")");
216 } 235 }