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