]>
Commit | Line | Data |
---|---|---|
b4c522fa IB |
1 | /** |
2 | * Computes RIPEMD-160 hashes of arbitrary data. RIPEMD-160 hashes are 20 byte quantities | |
3 | * that are like a checksum or CRC, but are more robust. | |
4 | * | |
5 | $(SCRIPT inhibitQuickIndex = 1;) | |
6 | ||
7 | $(DIVC quickindex, | |
8 | $(BOOKTABLE , | |
9 | $(TR $(TH Category) $(TH Functions) | |
10 | ) | |
11 | $(TR $(TDNW Template API) $(TD $(MYREF RIPEMD160) | |
12 | ) | |
13 | ) | |
14 | $(TR $(TDNW OOP API) $(TD $(MYREF RIPEMD160Digest)) | |
15 | ) | |
16 | $(TR $(TDNW Helpers) $(TD $(MYREF ripemd160Of)) | |
17 | ) | |
18 | ) | |
19 | ) | |
20 | ||
21 | * This module conforms to the APIs defined in $(MREF std, digest). To understand the | |
22 | * differences between the template and the OOP API, see $(MREF std, digest). | |
23 | * | |
5fee5ec3 | 24 | * This module publicly imports `std.digest` and can be used as a stand-alone |
b4c522fa IB |
25 | * module. |
26 | * | |
27 | * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). | |
28 | * | |
29 | * CTFE: | |
30 | * Digests do not work in CTFE | |
31 | * | |
32 | * Authors: | |
33 | * Kai Nacke $(BR) | |
34 | * The algorithm was designed by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel. $(BR) | |
35 | * The D implementation is a direct translation of the ANSI C implementation by Antoon Bosselaers. | |
36 | * | |
37 | * References: | |
38 | * $(UL | |
39 | * $(LI $(LINK2 http://homes.esat.kuleuven.be/~bosselae/ripemd160.html, The hash function RIPEMD-160)) | |
40 | * $(LI $(LINK2 http://en.wikipedia.org/wiki/RIPEMD-160, Wikipedia on RIPEMD-160)) | |
41 | * ) | |
42 | * | |
5fee5ec3 | 43 | * Source: $(PHOBOSSRC std/digest/ripemd.d) |
b4c522fa IB |
44 | * |
45 | */ | |
46 | ||
47 | module std.digest.ripemd; | |
48 | ||
49 | public import std.digest; | |
50 | ||
51 | /// | |
52 | @safe unittest | |
53 | { | |
54 | //Template API | |
55 | import std.digest.md; | |
56 | ||
57 | ubyte[20] hash = ripemd160Of("abc"); | |
58 | assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC"); | |
59 | ||
60 | //Feeding data | |
61 | ubyte[1024] data; | |
62 | RIPEMD160 md; | |
63 | md.start(); | |
64 | md.put(data[]); | |
65 | md.start(); //Start again | |
66 | md.put(data[]); | |
67 | hash = md.finish(); | |
68 | } | |
69 | ||
70 | /// | |
71 | @safe unittest | |
72 | { | |
73 | //OOP API | |
74 | import std.digest.md; | |
75 | ||
76 | auto md = new RIPEMD160Digest(); | |
77 | ubyte[] hash = md.digest("abc"); | |
78 | assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC"); | |
79 | ||
80 | //Feeding data | |
81 | ubyte[1024] data; | |
82 | md.put(data[]); | |
83 | md.reset(); //Start again | |
84 | md.put(data[]); | |
85 | hash = md.finish(); | |
86 | } | |
87 | ||
b4c522fa IB |
88 | /** |
89 | * Template API RIPEMD160 implementation. | |
5fee5ec3 | 90 | * See `std.digest` for differences between template and OOP API. |
b4c522fa IB |
91 | */ |
92 | struct RIPEMD160 | |
93 | { | |
5fee5ec3 | 94 | import core.bitop : rol; |
b4c522fa IB |
95 | private: |
96 | // magic initialization constants | |
97 | uint[5] _state = [0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0]; // state (ABCDE) | |
98 | ulong _count; //number of bits, modulo 2^64 | |
99 | ubyte[64] _buffer; // input buffer | |
100 | ||
101 | static immutable ubyte[64] _padding = | |
102 | [ | |
103 | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
104 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
105 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | |
106 | ]; | |
107 | ||
108 | // F, G, H, I and J are basic RIPEMD160 functions | |
109 | static @safe pure nothrow @nogc | |
110 | { | |
111 | uint F(uint x, uint y, uint z) { return x ^ y ^ z; } | |
112 | uint G(uint x, uint y, uint z) { return (x & y) | (~x & z); } | |
113 | uint H(uint x, uint y, uint z) { return (x | ~y) ^ z; } | |
114 | uint I(uint x, uint y, uint z) { return (x & z) | (y & ~z); } | |
115 | uint J(uint x, uint y, uint z) { return x ^ (y | ~z); } | |
116 | } | |
117 | ||
118 | /* | |
119 | * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. | |
120 | * Rotation is separate from addition to prevent recomputation. | |
121 | */ | |
122 | ||
123 | /* the ten basic operations FF() through III() */ | |
124 | static void FF(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s) | |
125 | @safe pure nothrow @nogc | |
126 | { | |
127 | a += F(b, c, d) + x; | |
5fee5ec3 IB |
128 | a = rol(a, s) + e; |
129 | c = rol(c, 10); | |
b4c522fa IB |
130 | } |
131 | ||
132 | static void GG(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s) | |
133 | @safe pure nothrow @nogc | |
134 | { | |
135 | a += G(b, c, d) + x + 0x5a827999UL; | |
5fee5ec3 IB |
136 | a = rol(a, s) + e; |
137 | c = rol(c, 10); | |
b4c522fa IB |
138 | } |
139 | ||
140 | static void HH(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s) | |
141 | @safe pure nothrow @nogc | |
142 | { | |
143 | a += H(b, c, d) + x + 0x6ed9eba1UL; | |
5fee5ec3 IB |
144 | a = rol(a, s) + e; |
145 | c = rol(c, 10); | |
b4c522fa IB |
146 | } |
147 | ||
148 | static void II(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s) | |
149 | @safe pure nothrow @nogc | |
150 | { | |
151 | a += I(b, c, d) + x + 0x8f1bbcdcUL; | |
5fee5ec3 IB |
152 | a = rol(a, s) + e; |
153 | c = rol(c, 10); | |
b4c522fa IB |
154 | } |
155 | ||
156 | static void JJ(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s) | |
157 | @safe pure nothrow @nogc | |
158 | { | |
159 | a += J(b, c, d) + x + 0xa953fd4eUL; | |
5fee5ec3 IB |
160 | a = rol(a, s) + e; |
161 | c = rol(c, 10); | |
b4c522fa IB |
162 | } |
163 | ||
164 | /* | |
165 | * FFF, GGG, HHH, and III transformations for parallel rounds 1, 2, 3, and 4. | |
166 | * Rotation is separate from addition to prevent recomputation. | |
167 | */ | |
168 | ||
169 | static void FFF(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s) | |
170 | @safe pure nothrow @nogc | |
171 | { | |
172 | a += F(b, c, d) + x; | |
5fee5ec3 IB |
173 | a = rol(a, s) + e; |
174 | c = rol(c, 10); | |
b4c522fa IB |
175 | } |
176 | ||
177 | static void GGG(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s) | |
178 | @safe pure nothrow @nogc | |
179 | { | |
180 | a += G(b, c, d) + x + 0x7a6d76e9UL; | |
5fee5ec3 IB |
181 | a = rol(a, s) + e; |
182 | c = rol(c, 10); | |
b4c522fa IB |
183 | } |
184 | ||
185 | static void HHH(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s) | |
186 | @safe pure nothrow @nogc | |
187 | { | |
188 | a += H(b, c, d) + x + 0x6d703ef3UL; | |
5fee5ec3 IB |
189 | a = rol(a, s) + e; |
190 | c = rol(c, 10); | |
b4c522fa IB |
191 | } |
192 | ||
193 | static void III(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s) | |
194 | @safe pure nothrow @nogc | |
195 | { | |
196 | a += I(b, c, d) + x + 0x5c4dd124UL; | |
5fee5ec3 IB |
197 | a = rol(a, s) + e; |
198 | c = rol(c, 10); | |
b4c522fa IB |
199 | } |
200 | ||
201 | static void JJJ(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s) | |
202 | @safe pure nothrow @nogc | |
203 | { | |
204 | a += J(b, c, d) + x + 0x50a28be6UL; | |
5fee5ec3 IB |
205 | a = rol(a, s) + e; |
206 | c = rol(c, 10); | |
b4c522fa IB |
207 | } |
208 | ||
209 | /* | |
210 | * RIPEMD160 basic transformation. Transforms state based on block. | |
211 | */ | |
212 | ||
213 | private void transform(const(ubyte[64])* block) | |
214 | pure nothrow @nogc | |
215 | { | |
216 | uint aa = _state[0], | |
217 | bb = _state[1], | |
218 | cc = _state[2], | |
219 | dd = _state[3], | |
220 | ee = _state[4]; | |
221 | uint aaa = _state[0], | |
222 | bbb = _state[1], | |
223 | ccc = _state[2], | |
224 | ddd = _state[3], | |
225 | eee = _state[4]; | |
226 | ||
227 | uint[16] x = void; | |
228 | ||
229 | version (BigEndian) | |
230 | { | |
231 | import std.bitmanip : littleEndianToNative; | |
232 | ||
233 | for (size_t i = 0; i < 16; i++) | |
234 | { | |
235 | x[i] = littleEndianToNative!uint(*cast(ubyte[4]*)&(*block)[i*4]); | |
236 | } | |
237 | } | |
238 | else | |
239 | { | |
240 | (cast(ubyte*) x.ptr)[0 .. 64] = (cast(ubyte*) block)[0 .. 64]; | |
241 | } | |
242 | ||
243 | /* round 1 */ | |
244 | FF(aa, bb, cc, dd, ee, x[ 0], 11); | |
245 | FF(ee, aa, bb, cc, dd, x[ 1], 14); | |
246 | FF(dd, ee, aa, bb, cc, x[ 2], 15); | |
247 | FF(cc, dd, ee, aa, bb, x[ 3], 12); | |
248 | FF(bb, cc, dd, ee, aa, x[ 4], 5); | |
249 | FF(aa, bb, cc, dd, ee, x[ 5], 8); | |
250 | FF(ee, aa, bb, cc, dd, x[ 6], 7); | |
251 | FF(dd, ee, aa, bb, cc, x[ 7], 9); | |
252 | FF(cc, dd, ee, aa, bb, x[ 8], 11); | |
253 | FF(bb, cc, dd, ee, aa, x[ 9], 13); | |
254 | FF(aa, bb, cc, dd, ee, x[10], 14); | |
255 | FF(ee, aa, bb, cc, dd, x[11], 15); | |
256 | FF(dd, ee, aa, bb, cc, x[12], 6); | |
257 | FF(cc, dd, ee, aa, bb, x[13], 7); | |
258 | FF(bb, cc, dd, ee, aa, x[14], 9); | |
259 | FF(aa, bb, cc, dd, ee, x[15], 8); | |
260 | ||
261 | /* round 2 */ | |
262 | GG(ee, aa, bb, cc, dd, x[ 7], 7); | |
263 | GG(dd, ee, aa, bb, cc, x[ 4], 6); | |
264 | GG(cc, dd, ee, aa, bb, x[13], 8); | |
265 | GG(bb, cc, dd, ee, aa, x[ 1], 13); | |
266 | GG(aa, bb, cc, dd, ee, x[10], 11); | |
267 | GG(ee, aa, bb, cc, dd, x[ 6], 9); | |
268 | GG(dd, ee, aa, bb, cc, x[15], 7); | |
269 | GG(cc, dd, ee, aa, bb, x[ 3], 15); | |
270 | GG(bb, cc, dd, ee, aa, x[12], 7); | |
271 | GG(aa, bb, cc, dd, ee, x[ 0], 12); | |
272 | GG(ee, aa, bb, cc, dd, x[ 9], 15); | |
273 | GG(dd, ee, aa, bb, cc, x[ 5], 9); | |
274 | GG(cc, dd, ee, aa, bb, x[ 2], 11); | |
275 | GG(bb, cc, dd, ee, aa, x[14], 7); | |
276 | GG(aa, bb, cc, dd, ee, x[11], 13); | |
277 | GG(ee, aa, bb, cc, dd, x[ 8], 12); | |
278 | ||
279 | /* round 3 */ | |
280 | HH(dd, ee, aa, bb, cc, x[ 3], 11); | |
281 | HH(cc, dd, ee, aa, bb, x[10], 13); | |
282 | HH(bb, cc, dd, ee, aa, x[14], 6); | |
283 | HH(aa, bb, cc, dd, ee, x[ 4], 7); | |
284 | HH(ee, aa, bb, cc, dd, x[ 9], 14); | |
285 | HH(dd, ee, aa, bb, cc, x[15], 9); | |
286 | HH(cc, dd, ee, aa, bb, x[ 8], 13); | |
287 | HH(bb, cc, dd, ee, aa, x[ 1], 15); | |
288 | HH(aa, bb, cc, dd, ee, x[ 2], 14); | |
289 | HH(ee, aa, bb, cc, dd, x[ 7], 8); | |
290 | HH(dd, ee, aa, bb, cc, x[ 0], 13); | |
291 | HH(cc, dd, ee, aa, bb, x[ 6], 6); | |
292 | HH(bb, cc, dd, ee, aa, x[13], 5); | |
293 | HH(aa, bb, cc, dd, ee, x[11], 12); | |
294 | HH(ee, aa, bb, cc, dd, x[ 5], 7); | |
295 | HH(dd, ee, aa, bb, cc, x[12], 5); | |
296 | ||
297 | /* round 4 */ | |
298 | II(cc, dd, ee, aa, bb, x[ 1], 11); | |
299 | II(bb, cc, dd, ee, aa, x[ 9], 12); | |
300 | II(aa, bb, cc, dd, ee, x[11], 14); | |
301 | II(ee, aa, bb, cc, dd, x[10], 15); | |
302 | II(dd, ee, aa, bb, cc, x[ 0], 14); | |
303 | II(cc, dd, ee, aa, bb, x[ 8], 15); | |
304 | II(bb, cc, dd, ee, aa, x[12], 9); | |
305 | II(aa, bb, cc, dd, ee, x[ 4], 8); | |
306 | II(ee, aa, bb, cc, dd, x[13], 9); | |
307 | II(dd, ee, aa, bb, cc, x[ 3], 14); | |
308 | II(cc, dd, ee, aa, bb, x[ 7], 5); | |
309 | II(bb, cc, dd, ee, aa, x[15], 6); | |
310 | II(aa, bb, cc, dd, ee, x[14], 8); | |
311 | II(ee, aa, bb, cc, dd, x[ 5], 6); | |
312 | II(dd, ee, aa, bb, cc, x[ 6], 5); | |
313 | II(cc, dd, ee, aa, bb, x[ 2], 12); | |
314 | ||
315 | /* round 5 */ | |
316 | JJ(bb, cc, dd, ee, aa, x[ 4], 9); | |
317 | JJ(aa, bb, cc, dd, ee, x[ 0], 15); | |
318 | JJ(ee, aa, bb, cc, dd, x[ 5], 5); | |
319 | JJ(dd, ee, aa, bb, cc, x[ 9], 11); | |
320 | JJ(cc, dd, ee, aa, bb, x[ 7], 6); | |
321 | JJ(bb, cc, dd, ee, aa, x[12], 8); | |
322 | JJ(aa, bb, cc, dd, ee, x[ 2], 13); | |
323 | JJ(ee, aa, bb, cc, dd, x[10], 12); | |
324 | JJ(dd, ee, aa, bb, cc, x[14], 5); | |
325 | JJ(cc, dd, ee, aa, bb, x[ 1], 12); | |
326 | JJ(bb, cc, dd, ee, aa, x[ 3], 13); | |
327 | JJ(aa, bb, cc, dd, ee, x[ 8], 14); | |
328 | JJ(ee, aa, bb, cc, dd, x[11], 11); | |
329 | JJ(dd, ee, aa, bb, cc, x[ 6], 8); | |
330 | JJ(cc, dd, ee, aa, bb, x[15], 5); | |
331 | JJ(bb, cc, dd, ee, aa, x[13], 6); | |
332 | ||
333 | /* parallel round 1 */ | |
334 | JJJ(aaa, bbb, ccc, ddd, eee, x[ 5], 8); | |
335 | JJJ(eee, aaa, bbb, ccc, ddd, x[14], 9); | |
336 | JJJ(ddd, eee, aaa, bbb, ccc, x[ 7], 9); | |
337 | JJJ(ccc, ddd, eee, aaa, bbb, x[ 0], 11); | |
338 | JJJ(bbb, ccc, ddd, eee, aaa, x[ 9], 13); | |
339 | JJJ(aaa, bbb, ccc, ddd, eee, x[ 2], 15); | |
340 | JJJ(eee, aaa, bbb, ccc, ddd, x[11], 15); | |
341 | JJJ(ddd, eee, aaa, bbb, ccc, x[ 4], 5); | |
342 | JJJ(ccc, ddd, eee, aaa, bbb, x[13], 7); | |
343 | JJJ(bbb, ccc, ddd, eee, aaa, x[ 6], 7); | |
344 | JJJ(aaa, bbb, ccc, ddd, eee, x[15], 8); | |
345 | JJJ(eee, aaa, bbb, ccc, ddd, x[ 8], 11); | |
346 | JJJ(ddd, eee, aaa, bbb, ccc, x[ 1], 14); | |
347 | JJJ(ccc, ddd, eee, aaa, bbb, x[10], 14); | |
348 | JJJ(bbb, ccc, ddd, eee, aaa, x[ 3], 12); | |
349 | JJJ(aaa, bbb, ccc, ddd, eee, x[12], 6); | |
350 | ||
351 | /* parallel round 2 */ | |
352 | III(eee, aaa, bbb, ccc, ddd, x[ 6], 9); | |
353 | III(ddd, eee, aaa, bbb, ccc, x[11], 13); | |
354 | III(ccc, ddd, eee, aaa, bbb, x[ 3], 15); | |
355 | III(bbb, ccc, ddd, eee, aaa, x[ 7], 7); | |
356 | III(aaa, bbb, ccc, ddd, eee, x[ 0], 12); | |
357 | III(eee, aaa, bbb, ccc, ddd, x[13], 8); | |
358 | III(ddd, eee, aaa, bbb, ccc, x[ 5], 9); | |
359 | III(ccc, ddd, eee, aaa, bbb, x[10], 11); | |
360 | III(bbb, ccc, ddd, eee, aaa, x[14], 7); | |
361 | III(aaa, bbb, ccc, ddd, eee, x[15], 7); | |
362 | III(eee, aaa, bbb, ccc, ddd, x[ 8], 12); | |
363 | III(ddd, eee, aaa, bbb, ccc, x[12], 7); | |
364 | III(ccc, ddd, eee, aaa, bbb, x[ 4], 6); | |
365 | III(bbb, ccc, ddd, eee, aaa, x[ 9], 15); | |
366 | III(aaa, bbb, ccc, ddd, eee, x[ 1], 13); | |
367 | III(eee, aaa, bbb, ccc, ddd, x[ 2], 11); | |
368 | ||
369 | /* parallel round 3 */ | |
370 | HHH(ddd, eee, aaa, bbb, ccc, x[15], 9); | |
371 | HHH(ccc, ddd, eee, aaa, bbb, x[ 5], 7); | |
372 | HHH(bbb, ccc, ddd, eee, aaa, x[ 1], 15); | |
373 | HHH(aaa, bbb, ccc, ddd, eee, x[ 3], 11); | |
374 | HHH(eee, aaa, bbb, ccc, ddd, x[ 7], 8); | |
375 | HHH(ddd, eee, aaa, bbb, ccc, x[14], 6); | |
376 | HHH(ccc, ddd, eee, aaa, bbb, x[ 6], 6); | |
377 | HHH(bbb, ccc, ddd, eee, aaa, x[ 9], 14); | |
378 | HHH(aaa, bbb, ccc, ddd, eee, x[11], 12); | |
379 | HHH(eee, aaa, bbb, ccc, ddd, x[ 8], 13); | |
380 | HHH(ddd, eee, aaa, bbb, ccc, x[12], 5); | |
381 | HHH(ccc, ddd, eee, aaa, bbb, x[ 2], 14); | |
382 | HHH(bbb, ccc, ddd, eee, aaa, x[10], 13); | |
383 | HHH(aaa, bbb, ccc, ddd, eee, x[ 0], 13); | |
384 | HHH(eee, aaa, bbb, ccc, ddd, x[ 4], 7); | |
385 | HHH(ddd, eee, aaa, bbb, ccc, x[13], 5); | |
386 | ||
387 | /* parallel round 4 */ | |
388 | GGG(ccc, ddd, eee, aaa, bbb, x[ 8], 15); | |
389 | GGG(bbb, ccc, ddd, eee, aaa, x[ 6], 5); | |
390 | GGG(aaa, bbb, ccc, ddd, eee, x[ 4], 8); | |
391 | GGG(eee, aaa, bbb, ccc, ddd, x[ 1], 11); | |
392 | GGG(ddd, eee, aaa, bbb, ccc, x[ 3], 14); | |
393 | GGG(ccc, ddd, eee, aaa, bbb, x[11], 14); | |
394 | GGG(bbb, ccc, ddd, eee, aaa, x[15], 6); | |
395 | GGG(aaa, bbb, ccc, ddd, eee, x[ 0], 14); | |
396 | GGG(eee, aaa, bbb, ccc, ddd, x[ 5], 6); | |
397 | GGG(ddd, eee, aaa, bbb, ccc, x[12], 9); | |
398 | GGG(ccc, ddd, eee, aaa, bbb, x[ 2], 12); | |
399 | GGG(bbb, ccc, ddd, eee, aaa, x[13], 9); | |
400 | GGG(aaa, bbb, ccc, ddd, eee, x[ 9], 12); | |
401 | GGG(eee, aaa, bbb, ccc, ddd, x[ 7], 5); | |
402 | GGG(ddd, eee, aaa, bbb, ccc, x[10], 15); | |
403 | GGG(ccc, ddd, eee, aaa, bbb, x[14], 8); | |
404 | ||
405 | /* parallel round 5 */ | |
406 | FFF(bbb, ccc, ddd, eee, aaa, x[12] , 8); | |
407 | FFF(aaa, bbb, ccc, ddd, eee, x[15] , 5); | |
408 | FFF(eee, aaa, bbb, ccc, ddd, x[10] , 12); | |
409 | FFF(ddd, eee, aaa, bbb, ccc, x[ 4] , 9); | |
410 | FFF(ccc, ddd, eee, aaa, bbb, x[ 1] , 12); | |
411 | FFF(bbb, ccc, ddd, eee, aaa, x[ 5] , 5); | |
412 | FFF(aaa, bbb, ccc, ddd, eee, x[ 8] , 14); | |
413 | FFF(eee, aaa, bbb, ccc, ddd, x[ 7] , 6); | |
414 | FFF(ddd, eee, aaa, bbb, ccc, x[ 6] , 8); | |
415 | FFF(ccc, ddd, eee, aaa, bbb, x[ 2] , 13); | |
416 | FFF(bbb, ccc, ddd, eee, aaa, x[13] , 6); | |
417 | FFF(aaa, bbb, ccc, ddd, eee, x[14] , 5); | |
418 | FFF(eee, aaa, bbb, ccc, ddd, x[ 0] , 15); | |
419 | FFF(ddd, eee, aaa, bbb, ccc, x[ 3] , 13); | |
420 | FFF(ccc, ddd, eee, aaa, bbb, x[ 9] , 11); | |
421 | FFF(bbb, ccc, ddd, eee, aaa, x[11] , 11); | |
422 | ||
423 | /* combine results */ | |
424 | ddd += cc + _state[1]; /* final result for _state[0] */ | |
425 | _state[1] = _state[2] + dd + eee; | |
426 | _state[2] = _state[3] + ee + aaa; | |
427 | _state[3] = _state[4] + aa + bbb; | |
428 | _state[4] = _state[0] + bb + ccc; | |
429 | _state[0] = ddd; | |
430 | ||
431 | //Zeroize sensitive information. | |
432 | x[] = 0; | |
433 | } | |
434 | ||
435 | public: | |
436 | enum blockSize = 512; | |
437 | ||
438 | /** | |
439 | * Use this to feed the digest with data. | |
440 | * Also implements the $(REF isOutputRange, std,range,primitives) | |
5fee5ec3 | 441 | * interface for `ubyte` and `const(ubyte)[]`. |
b4c522fa IB |
442 | * |
443 | * Example: | |
444 | * ---- | |
445 | * RIPEMD160 dig; | |
446 | * dig.put(cast(ubyte) 0); //single ubyte | |
447 | * dig.put(cast(ubyte) 0, cast(ubyte) 0); //variadic | |
448 | * ubyte[10] buf; | |
449 | * dig.put(buf); //buffer | |
450 | * ---- | |
451 | */ | |
452 | void put(scope const(ubyte)[] data...) @trusted pure nothrow @nogc | |
453 | { | |
454 | uint i, index, partLen; | |
455 | auto inputLen = data.length; | |
456 | ||
457 | //Compute number of bytes mod 64 | |
458 | index = (cast(uint)_count >> 3) & (64 - 1); | |
459 | ||
460 | //Update number of bits | |
461 | _count += inputLen * 8; | |
462 | ||
463 | partLen = 64 - index; | |
464 | ||
465 | //Transform as many times as possible | |
466 | if (inputLen >= partLen) | |
467 | { | |
468 | (&_buffer[index])[0 .. partLen] = data.ptr[0 .. partLen]; | |
469 | transform(&_buffer); | |
470 | ||
471 | for (i = partLen; i + 63 < inputLen; i += 64) | |
472 | { | |
473 | transform(cast(const(ubyte[64])*)(data[i .. i + 64].ptr)); | |
474 | } | |
475 | ||
476 | index = 0; | |
477 | } | |
478 | else | |
479 | { | |
480 | i = 0; | |
481 | } | |
482 | ||
483 | /* Buffer remaining input */ | |
484 | if (inputLen - i) | |
485 | (&_buffer[index])[0 .. inputLen-i] = (&data[i])[0 .. inputLen-i]; | |
486 | } | |
487 | ||
488 | /** | |
489 | * Used to (re)initialize the RIPEMD160 digest. | |
490 | * | |
491 | * Note: | |
492 | * For this RIPEMD160 Digest implementation calling start after default construction | |
493 | * is not necessary. Calling start is only necessary to reset the Digest. | |
494 | * | |
495 | * Generic code which deals with different Digest types should always call start though. | |
496 | * | |
497 | * Example: | |
498 | * -------- | |
499 | * RIPEMD160 digest; | |
500 | * //digest.start(); //Not necessary | |
501 | * digest.put(0); | |
502 | * -------- | |
503 | */ | |
504 | void start() @safe pure nothrow @nogc | |
505 | { | |
506 | this = RIPEMD160.init; | |
507 | } | |
508 | ||
509 | /** | |
510 | * Returns the finished RIPEMD160 hash. This also calls $(LREF start) to | |
511 | * reset the internal state. | |
512 | * | |
513 | * Example: | |
514 | * -------- | |
515 | * //Simple example | |
516 | * RIPEMD160 hash; | |
517 | * hash.start(); | |
518 | * hash.put(cast(ubyte) 0); | |
519 | * ubyte[20] result = hash.finish(); | |
520 | * assert(toHexString(result) == "C81B94933420221A7AC004A90242D8B1D3E5070D"); | |
521 | * -------- | |
522 | */ | |
523 | ubyte[20] finish() @trusted pure nothrow @nogc | |
524 | { | |
525 | import std.bitmanip : nativeToLittleEndian; | |
526 | ||
527 | ubyte[20] data = void; | |
528 | ubyte[8] bits = void; | |
529 | uint index, padLen; | |
530 | ||
531 | //Save number of bits | |
532 | bits[0 .. 8] = nativeToLittleEndian(_count)[]; | |
533 | ||
534 | //Pad out to 56 mod 64 | |
535 | index = (cast(uint)_count >> 3) & (64 - 1); | |
536 | padLen = (index < 56) ? (56 - index) : (120 - index); | |
537 | put(_padding[0 .. padLen]); | |
538 | ||
539 | //Append length (before padding) | |
540 | put(bits); | |
541 | ||
542 | //Store state in digest | |
543 | data[0 .. 4] = nativeToLittleEndian(_state[0])[]; | |
544 | data[4 .. 8] = nativeToLittleEndian(_state[1])[]; | |
545 | data[8 .. 12] = nativeToLittleEndian(_state[2])[]; | |
546 | data[12 .. 16] = nativeToLittleEndian(_state[3])[]; | |
547 | data[16 .. 20] = nativeToLittleEndian(_state[4])[]; | |
548 | ||
549 | /* Zeroize sensitive information. */ | |
550 | start(); | |
551 | return data; | |
552 | } | |
553 | } | |
554 | ||
555 | /// | |
556 | @safe unittest | |
557 | { | |
558 | //Simple example, hashing a string using ripemd160Of helper function | |
559 | ubyte[20] hash = ripemd160Of("abc"); | |
560 | //Let's get a hash string | |
561 | assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC"); | |
562 | } | |
563 | ||
564 | /// | |
565 | @safe unittest | |
566 | { | |
567 | //Using the basic API | |
568 | RIPEMD160 hash; | |
569 | hash.start(); | |
570 | ubyte[1024] data; | |
571 | //Initialize data here... | |
572 | hash.put(data); | |
573 | ubyte[20] result = hash.finish(); | |
574 | } | |
575 | ||
576 | /// | |
577 | @safe unittest | |
578 | { | |
579 | //Let's use the template features: | |
580 | void doSomething(T)(ref T hash) | |
581 | if (isDigest!T) | |
582 | { | |
583 | hash.put(cast(ubyte) 0); | |
584 | } | |
585 | RIPEMD160 md; | |
586 | md.start(); | |
587 | doSomething(md); | |
588 | assert(toHexString(md.finish()) == "C81B94933420221A7AC004A90242D8B1D3E5070D"); | |
589 | } | |
590 | ||
591 | /// | |
592 | @safe unittest | |
593 | { | |
594 | //Simple example | |
595 | RIPEMD160 hash; | |
596 | hash.start(); | |
597 | hash.put(cast(ubyte) 0); | |
598 | ubyte[20] result = hash.finish(); | |
599 | assert(toHexString(result) == "C81B94933420221A7AC004A90242D8B1D3E5070D"); | |
600 | } | |
601 | ||
602 | @safe unittest | |
603 | { | |
604 | assert(isDigest!RIPEMD160); | |
605 | } | |
606 | ||
607 | @system unittest | |
608 | { | |
5fee5ec3 | 609 | import std.conv : hexString; |
b4c522fa IB |
610 | import std.range; |
611 | ||
612 | ubyte[20] digest; | |
613 | ||
614 | RIPEMD160 md; | |
615 | md.put(cast(ubyte[])"abcdef"); | |
616 | md.start(); | |
617 | md.put(cast(ubyte[])""); | |
5fee5ec3 | 618 | assert(md.finish() == cast(ubyte[]) hexString!"9c1185a5c5e9fc54612808977ee8f548b2258d31"); |
b4c522fa IB |
619 | |
620 | digest = ripemd160Of(""); | |
5fee5ec3 | 621 | assert(digest == cast(ubyte[]) hexString!"9c1185a5c5e9fc54612808977ee8f548b2258d31"); |
b4c522fa IB |
622 | |
623 | digest = ripemd160Of("a"); | |
5fee5ec3 | 624 | assert(digest == cast(ubyte[]) hexString!"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"); |
b4c522fa IB |
625 | |
626 | digest = ripemd160Of("abc"); | |
5fee5ec3 | 627 | assert(digest == cast(ubyte[]) hexString!"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"); |
b4c522fa IB |
628 | |
629 | digest = ripemd160Of("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); | |
5fee5ec3 | 630 | assert(digest == cast(ubyte[]) hexString!"12a053384a9c0c88e405a06c27dcf49ada62eb2b"); |
b4c522fa IB |
631 | |
632 | digest = ripemd160Of("message digest"); | |
5fee5ec3 | 633 | assert(digest == cast(ubyte[]) hexString!"5d0689ef49d2fae572b881b123a85ffa21595f36"); |
b4c522fa IB |
634 | |
635 | digest = ripemd160Of("abcdefghijklmnopqrstuvwxyz"); | |
5fee5ec3 | 636 | assert(digest == cast(ubyte[]) hexString!"f71c27109c692c1b56bbdceb5b9d2865b3708dbc"); |
b4c522fa IB |
637 | |
638 | digest = ripemd160Of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); | |
5fee5ec3 | 639 | assert(digest == cast(ubyte[]) hexString!"b0e20b6e3116640286ed3a87a5713079b21f5189"); |
b4c522fa IB |
640 | |
641 | digest = ripemd160Of("1234567890123456789012345678901234567890"~ | |
642 | "1234567890123456789012345678901234567890"); | |
5fee5ec3 | 643 | assert(digest == cast(ubyte[]) hexString!"9b752e45573d4b39f4dbd3323cab82bf63326bfb"); |
b4c522fa | 644 | |
5fee5ec3 IB |
645 | enum ubyte[20] input = cast(ubyte[20]) hexString!"f71c27109c692c1b56bbdceb5b9d2865b3708dbc"; |
646 | assert(toHexString(input) | |
b4c522fa IB |
647 | == "F71C27109C692C1B56BBDCEB5B9D2865B3708DBC"); |
648 | ||
649 | ubyte[] onemilliona = new ubyte[1000000]; | |
650 | onemilliona[] = 'a'; | |
651 | digest = ripemd160Of(onemilliona); | |
5fee5ec3 | 652 | assert(digest == cast(ubyte[]) hexString!"52783243c1697bdbe16d37f97f68f08325dc1528"); |
b4c522fa IB |
653 | |
654 | auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000); | |
655 | digest = ripemd160Of(oneMillionRange); | |
5fee5ec3 | 656 | assert(digest == cast(ubyte[]) hexString!"52783243c1697bdbe16d37f97f68f08325dc1528"); |
b4c522fa IB |
657 | } |
658 | ||
659 | /** | |
660 | * This is a convenience alias for $(REF digest, std,digest) using the | |
661 | * RIPEMD160 implementation. | |
662 | */ | |
663 | //simple alias doesn't work here, hope this gets inlined... | |
664 | auto ripemd160Of(T...)(T data) | |
665 | { | |
666 | return digest!(RIPEMD160, T)(data); | |
667 | } | |
668 | ||
669 | /// | |
670 | @safe unittest | |
671 | { | |
672 | ubyte[20] hash = ripemd160Of("abc"); | |
673 | assert(hash == digest!RIPEMD160("abc")); | |
674 | } | |
675 | ||
676 | /** | |
677 | * OOP API RIPEMD160 implementation. | |
5fee5ec3 | 678 | * See `std.digest` for differences between template and OOP API. |
b4c522fa IB |
679 | * |
680 | * This is an alias for $(D $(REF WrapperDigest, std,digest)!RIPEMD160), | |
681 | * see there for more information. | |
682 | */ | |
683 | alias RIPEMD160Digest = WrapperDigest!RIPEMD160; | |
684 | ||
685 | /// | |
686 | @safe unittest | |
687 | { | |
688 | //Simple example, hashing a string using Digest.digest helper function | |
689 | auto md = new RIPEMD160Digest(); | |
690 | ubyte[] hash = md.digest("abc"); | |
691 | //Let's get a hash string | |
692 | assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC"); | |
693 | } | |
694 | ||
695 | /// | |
696 | @system unittest | |
697 | { | |
698 | //Let's use the OOP features: | |
699 | void test(Digest dig) | |
700 | { | |
701 | dig.put(cast(ubyte) 0); | |
702 | } | |
703 | auto md = new RIPEMD160Digest(); | |
704 | test(md); | |
705 | ||
706 | //Let's use a custom buffer: | |
707 | ubyte[20] buf; | |
708 | ubyte[] result = md.finish(buf[]); | |
709 | assert(toHexString(result) == "C81B94933420221A7AC004A90242D8B1D3E5070D"); | |
710 | } | |
711 | ||
712 | @system unittest | |
713 | { | |
5fee5ec3 | 714 | import std.conv : hexString; |
b4c522fa IB |
715 | auto md = new RIPEMD160Digest(); |
716 | ||
717 | md.put(cast(ubyte[])"abcdef"); | |
718 | md.reset(); | |
719 | md.put(cast(ubyte[])""); | |
5fee5ec3 | 720 | assert(md.finish() == cast(ubyte[]) hexString!"9c1185a5c5e9fc54612808977ee8f548b2258d31"); |
b4c522fa IB |
721 | |
722 | md.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz"); | |
723 | ubyte[20] result; | |
724 | auto result2 = md.finish(result[]); | |
5fee5ec3 | 725 | assert(result[0 .. 20] == result2 && result2 == cast(ubyte[]) hexString!"f71c27109c692c1b56bbdceb5b9d2865b3708dbc"); |
b4c522fa IB |
726 | |
727 | debug | |
728 | { | |
729 | import std.exception; | |
730 | assertThrown!Error(md.finish(result[0 .. 19])); | |
731 | } | |
732 | ||
733 | assert(md.length == 20); | |
734 | ||
5fee5ec3 | 735 | assert(md.digest("") == cast(ubyte[]) hexString!"9c1185a5c5e9fc54612808977ee8f548b2258d31"); |
b4c522fa | 736 | |
5fee5ec3 | 737 | assert(md.digest("a") == cast(ubyte[]) hexString!"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"); |
b4c522fa | 738 | |
5fee5ec3 | 739 | assert(md.digest("abc") == cast(ubyte[]) hexString!"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"); |
b4c522fa IB |
740 | |
741 | assert(md.digest("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") | |
5fee5ec3 | 742 | == cast(ubyte[]) hexString!"12a053384a9c0c88e405a06c27dcf49ada62eb2b"); |
b4c522fa | 743 | |
5fee5ec3 | 744 | assert(md.digest("message digest") == cast(ubyte[]) hexString!"5d0689ef49d2fae572b881b123a85ffa21595f36"); |
b4c522fa IB |
745 | |
746 | assert(md.digest("abcdefghijklmnopqrstuvwxyz") | |
5fee5ec3 | 747 | == cast(ubyte[]) hexString!"f71c27109c692c1b56bbdceb5b9d2865b3708dbc"); |
b4c522fa IB |
748 | |
749 | assert(md.digest("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") | |
5fee5ec3 | 750 | == cast(ubyte[]) hexString!"b0e20b6e3116640286ed3a87a5713079b21f5189"); |
b4c522fa IB |
751 | |
752 | assert(md.digest("1234567890123456789012345678901234567890", | |
753 | "1234567890123456789012345678901234567890") | |
5fee5ec3 | 754 | == cast(ubyte[]) hexString!"9b752e45573d4b39f4dbd3323cab82bf63326bfb"); |
b4c522fa IB |
755 | |
756 | assert(md.digest(new ubyte[160/8]) // 160 zero bits | |
5fee5ec3 | 757 | == cast(ubyte[]) hexString!"5c00bd4aca04a9057c09b20b05f723f2e23deb65"); |
b4c522fa | 758 | } |