Mercurial > projects > dcrypt
comparison dcrypt/crypto/hashes/MD4.d @ 26:176c933827a8
Implemented MD4. Refactored MD5. Replaced all instances of 'version (UnitTest)' with 'debug (UnitTest)'.
author | Thomas Dixon <reikon@reikon.us> |
---|---|
date | Sun, 01 Mar 2009 13:06:48 -0500 |
parents | |
children | 8b5eaf3c2979 |
comparison
equal
deleted
inserted
replaced
25:528676d20398 | 26:176c933827a8 |
---|---|
1 /** | |
2 * This file is part of the dcrypt project. | |
3 * | |
4 * Copyright: Copyright (C) dcrypt contributors 2009. All rights reserved. | |
5 * License: MIT | |
6 * Authors: Thomas Dixon | |
7 */ | |
8 | |
9 module dcrypt.crypto.hashes.MD4; | |
10 | |
11 public import dcrypt.crypto.Hash; | |
12 | |
13 /** | |
14 * Implementation of Ron Rivest's MD4. | |
15 * | |
16 * Conforms: RFC 1320 | |
17 * References: http://www.faqs.org/rfcs/rfc1320.html | |
18 * Bugs: MD4 is not cryptographically secure. | |
19 */ | |
20 class MD4 : Hash { | |
21 private uint h0, h1, h2, h3; | |
22 | |
23 // Shift amounts | |
24 private enum { | |
25 S11 = 3, | |
26 S12 = 7, | |
27 S13 = 11, | |
28 S14 = 19, | |
29 | |
30 S21 = 3, | |
31 S22 = 5, | |
32 S23 = 9, | |
33 S24 = 13, | |
34 | |
35 S31 = 3, | |
36 S32 = 9, | |
37 S33 = 11, | |
38 S34 = 15 | |
39 }; | |
40 | |
41 this (void[] input_=null) { | |
42 reset(); | |
43 super(input_); | |
44 } | |
45 | |
46 uint blockSize() { | |
47 return 64; | |
48 } | |
49 | |
50 uint digestSize() { | |
51 return 16; | |
52 } | |
53 | |
54 char[] name() { | |
55 return "MD4"; | |
56 } | |
57 | |
58 void transform(ubyte[] input) { | |
59 uint[] w = new uint[16]; | |
60 | |
61 for (int i = 0, j = 0; i < 16; i++,j+=int.sizeof) | |
62 w[i] = ByteConverter.LittleEndian.to!(uint)(input[j..j+int.sizeof]); | |
63 | |
64 uint a = h0, | |
65 b = h1, | |
66 c = h2, | |
67 d = h3; | |
68 | |
69 // Round 1 | |
70 ff(a, b, c, d, w[ 0], S11); | |
71 ff(d, a, b, c, w[ 1], S12); | |
72 ff(c, d, a, b, w[ 2], S13); | |
73 ff(b, c, d, a, w[ 3], S14); | |
74 ff(a, b, c, d, w[ 4], S11); | |
75 ff(d, a, b, c, w[ 5], S12); | |
76 ff(c, d, a, b, w[ 6], S13); | |
77 ff(b, c, d, a, w[ 7], S14); | |
78 ff(a, b, c, d, w[ 8], S11); | |
79 ff(d, a, b, c, w[ 9], S12); | |
80 ff(c, d, a, b, w[10], S13); | |
81 ff(b, c, d, a, w[11], S14); | |
82 ff(a, b, c, d, w[12], S11); | |
83 ff(d, a, b, c, w[13], S12); | |
84 ff(c, d, a, b, w[14], S13); | |
85 ff(b, c, d, a, w[15], S14); | |
86 | |
87 // Round 2 | |
88 gg(a, b, c, d, w[ 0], S21); | |
89 gg(d, a, b, c, w[ 4], S22); | |
90 gg(c, d, a, b, w[ 8], S23); | |
91 gg(b, c, d, a, w[12], S24); | |
92 gg(a, b, c, d, w[ 1], S21); | |
93 gg(d, a, b, c, w[ 5], S22); | |
94 gg(c, d, a, b, w[ 9], S23); | |
95 gg(b, c, d, a, w[13], S24); | |
96 gg(a, b, c, d, w[ 2], S21); | |
97 gg(d, a, b, c, w[ 6], S22); | |
98 gg(c, d, a, b, w[10], S23); | |
99 gg(b, c, d, a, w[14], S24); | |
100 gg(a, b, c, d, w[ 3], S21); | |
101 gg(d, a, b, c, w[ 7], S22); | |
102 gg(c, d, a, b, w[11], S23); | |
103 gg(b, c, d, a, w[15], S24); | |
104 | |
105 // Round 3 | |
106 hh(a, b, c, d, w[ 0], S31); | |
107 hh(d, a, b, c, w[ 8], S32); | |
108 hh(c, d, a, b, w[ 4], S33); | |
109 hh(b, c, d, a, w[12], S34); | |
110 hh(a, b, c, d, w[ 2], S31); | |
111 hh(d, a, b, c, w[10], S32); | |
112 hh(c, d, a, b, w[ 6], S33); | |
113 hh(b, c, d, a, w[14], S34); | |
114 hh(a, b, c, d, w[ 1], S31); | |
115 hh(d, a, b, c, w[ 9], S32); | |
116 hh(c, d, a, b, w[ 5], S33); | |
117 hh(b, c, d, a, w[13], S34); | |
118 hh(a, b, c, d, w[ 3], S31); | |
119 hh(d, a, b, c, w[11], S32); | |
120 hh(c, d, a, b, w[ 7], S33); | |
121 hh(b, c, d, a, w[15], S34); | |
122 | |
123 h0 += a; | |
124 h1 += b; | |
125 h2 += c; | |
126 h3 += d; | |
127 } | |
128 | |
129 private uint f(uint x, uint y, uint z) { | |
130 return (x&y)|(~x&z); | |
131 } | |
132 | |
133 private uint h(uint x, uint y, uint z) { | |
134 return x^y^z; | |
135 } | |
136 | |
137 private uint g(uint x, uint y, uint z) { | |
138 return (x&y)|(x&z)|(y&z); | |
139 } | |
140 | |
141 private void ff(ref uint a, uint b, uint c, uint d, uint x, uint s) { | |
142 a += f(b, c, d) + x; | |
143 a = Bitwise.rotateLeft(a, s); | |
144 } | |
145 | |
146 private void gg(ref uint a, uint b, uint c, uint d, uint x, uint s) { | |
147 a += g(b, c, d) + x + 0x5a827999u; | |
148 a = Bitwise.rotateLeft(a, s); | |
149 } | |
150 | |
151 private void hh(ref uint a, uint b, uint c, uint d, uint x, uint s) { | |
152 a += h(b, c, d) + x + 0x6ed9eba1u; | |
153 a = Bitwise.rotateLeft(a, s); | |
154 } | |
155 | |
156 ubyte[] digest() { | |
157 padMessage(MODE_MD); | |
158 ubyte[] result = new ubyte[digestSize]; | |
159 | |
160 result[0..4] = ByteConverter.LittleEndian.from!(uint)(h0); | |
161 result[4..8] = ByteConverter.LittleEndian.from!(uint)(h1); | |
162 result[8..12] = ByteConverter.LittleEndian.from!(uint)(h2); | |
163 result[12..16] = ByteConverter.LittleEndian.from!(uint)(h3); | |
164 | |
165 reset(); | |
166 return result; | |
167 } | |
168 | |
169 void reset() { | |
170 super.reset(); | |
171 h0 = 0x67452301u; | |
172 h1 = 0xefcdab89u; | |
173 h2 = 0x98badcfeu; | |
174 h3 = 0x10325476u; | |
175 } | |
176 | |
177 MD4 copy() { | |
178 MD4 h = new MD4(buffer[0..index]); | |
179 h.bytes = bytes; | |
180 h.h0 = h0; | |
181 h.h1 = h1; | |
182 h.h2 = h2; | |
183 h.h3 = h3; | |
184 return h; | |
185 } | |
186 | |
187 debug (UnitTest) { | |
188 // Found in Tango <3 | |
189 unittest { | |
190 static const char[][] test_inputs = [ | |
191 "", | |
192 "a", | |
193 "abc", | |
194 "message digest", | |
195 "abcdefghijklmnopqrstuvwxyz", | |
196 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", | |
197 "12345678901234567890123456789012345678901234567890123456789012345678901234567890" | |
198 ]; | |
199 | |
200 static const char[][] test_results = [ | |
201 "31d6cfe0d16ae931b73c59d7e0c089c0", | |
202 "bde52cb31de33e46245e05fbdbd6fb24", | |
203 "a448017aaf21d8525fc10ae87aa6729d", | |
204 "d9130a8164549fe818874806e1c7014b", | |
205 "d79e1c308aa5bbcdeea8ed63df412da9", | |
206 "043f8582f241db351ce627e153e7f0e4", | |
207 "e33b4ddc9c38f2199c3e7b164fcc0536" | |
208 ]; | |
209 | |
210 MD4 h = new MD4(); | |
211 foreach (uint i, char[] input; test_inputs) { | |
212 h.update(input); | |
213 char[] digest = h.hexDigest(); | |
214 assert(digest == test_results[i], | |
215 h.name~": ("~digest~") != ("~test_results[i]~")"); | |
216 } | |
217 } | |
218 } | |
219 } |