1 /*******************************************************************************
2 
3         This module implements the Ripemd160 algorithm by Hans Dobbertin,
4         Antoon Bosselaers and Bart Preneel.
5 
6         See http://homes.esat.kuleuven.be/~bosselae/ripemd160.html for more
7         information.
8 
9         The implementation is based on:
10         RIPEMD-160 software written by Antoon Bosselaers,
11  		available at http://www.esat.kuleuven.ac.be/~cosicart/ps/AB-9601/
12 
13         Copyright:
14             Copyright (c) 2009 Tango contributors.
15             Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH.
16             All rights reserved.
17 
18         License:
19             Tango Dual License: 3-Clause BSD License / Academic Free License v3.0.
20             See LICENSE_TANGO.txt for details.
21 
22         Version: Initial release: Sep 2009
23 
24         Authors: Kai Nacke
25 
26 *******************************************************************************/
27 
28 module ocean.util.digest.Ripemd160;
29 
30 import ocean.meta.types.Qualifiers;
31 
32 import ocean.util.digest.MerkleDamgard;
33 
34 public  import ocean.util.digest.Digest;
35 
36 version (unittest) import ocean.core.Test;
37 
38 /*******************************************************************************
39 
40 *******************************************************************************/
41 
42 final class Ripemd160 : MerkleDamgard
43 {
44         private uint[5]        context;
45         private static immutable uint     padChar = 0x80;
46 
47         /***********************************************************************
48 
49         ***********************************************************************/
50 
51         private static const(uint[5]) initial =
52         [
53 				0x67452301,
54 				0xefcdab89,
55 				0x98badcfe,
56 				0x10325476,
57 				0xc3d2e1f0
58         ];
59 
60         /***********************************************************************
61 
62         	Construct a Ripemd160
63 
64          ***********************************************************************/
65 
66         this() { }
67 
68         /***********************************************************************
69 
70         	The size of a Ripemd160 digest is 20 bytes
71 
72          ***********************************************************************/
73 
74         override uint digestSize() {return 20;}
75 
76 
77         /***********************************************************************
78 
79         	Initialize the cipher
80 
81         	Remarks:
82         		Returns the cipher state to it's initial value
83 
84          ***********************************************************************/
85 
86         override void reset()
87         {
88         	super.reset();
89         	context[] = initial[];
90         }
91 
92         /***********************************************************************
93 
94         	Obtain the digest
95 
96         	Returns:
97         		the digest
98 
99         	Remarks:
100         		Returns a digest of the current cipher state, this may be the
101         		final digest, or a digest of the state between calls to update()
102 
103          ***********************************************************************/
104 
105         override void createDigest(ubyte[] buf)
106         {
107             version (BigEndian)
108             	ByteSwap.swap32 (context.ptr, context.length * uint.sizeof);
109 
110         	buf[] = cast(ubyte[]) context;
111         }
112 
113 
114         /***********************************************************************
115 
116          	block size
117 
118         	Returns:
119         	the block size
120 
121         	Remarks:
122         	Specifies the size (in bytes) of the block of data to pass to
123         	each call to transform(). For Ripemd160 the blockSize is 64.
124 
125          ***********************************************************************/
126 
127         protected override uint blockSize() { return 64; }
128 
129         /***********************************************************************
130 
131         	Length padding size
132 
133         	Returns:
134         	the length padding size
135 
136         	Remarks:
137         	Specifies the size (in bytes) of the padding which uses the
138         	length of the data which has been ciphered, this padding is
139         	carried out by the padLength method. For Ripemd160 the addSize is 8.
140 
141          ***********************************************************************/
142 
143         protected override uint addSize()   { return 8;  }
144 
145         /***********************************************************************
146 
147         	Pads the cipher data
148 
149         	Params:
150         	at = a slice of the cipher buffer to fill with padding
151 
152         	Remarks:
153         	Fills the passed buffer slice with the appropriate padding for
154         	the final call to transform(). This padding will fill the cipher
155         	buffer up to blockSize()-addSize().
156 
157          ***********************************************************************/
158 
159         protected override void padMessage(ubyte[] at)
160         {
161         	at[0] = padChar;
162         	at[1..at.length] = 0;
163         }
164 
165         /***********************************************************************
166 
167         	Performs the length padding
168 
169         	Params:
170         	at     = the slice of the cipher buffer to fill with padding
171         	length = the length of the data which has been ciphered
172 
173         	Remarks:
174         	Fills the passed buffer slice with addSize() bytes of padding
175         	based on the length in bytes of the input data which has been
176         	ciphered.
177 
178          ***********************************************************************/
179 
180         protected override void padLength(ubyte[] at, ulong length)
181         {
182         	length <<= 3;
183         	littleEndian64((cast(ubyte*)&length)[0..8],cast(ulong[]) at);
184         }
185 
186         /***********************************************************************
187 
188         	Performs the cipher on a block of data
189 
190         	Params:
191         	input = the block of data to cipher
192 
193         	Remarks:
194         	The actual cipher algorithm is carried out by this method on
195         	the passed block of data. This method is called for every
196         	blockSize() bytes of input data and once more with the remaining
197         	data padded to blockSize().
198 
199          ***********************************************************************/
200 
201         protected override void transform(ubyte[] input)
202         {
203         	uint al, bl, cl, dl, el;
204         	uint ar, br, cr, dr, er;
205             uint[16] x;
206 
207             littleEndian32(input,x);
208 
209             al = ar = context[0];
210             bl = br = context[1];
211             cl = cr = context[2];
212             dl = dr = context[3];
213             el = er = context[4];
214 
215             // Round 1 and parallel round 1
216             al = rotateLeft(al + (bl ^ cl ^ dl) + x[0], 11) + el;
217             ar = rotateLeft(ar + (br ^ (cr | ~dr)) + x[5] + 0x50a28be6, 8) + er;
218             cl = rotateLeft(cl, 10);
219             cr = rotateLeft(cr, 10);
220             el = rotateLeft(el + (al ^ bl ^ cl) + x[1], 14) + dl;
221             er = rotateLeft(er + (ar ^ (br | ~cr)) + x[14] + 0x50a28be6, 9) + dr;
222             bl = rotateLeft(bl, 10);
223             br = rotateLeft(br, 10);
224             dl = rotateLeft(dl + (el ^ al ^ bl) + x[2], 15) + cl;
225             dr = rotateLeft(dr + (er ^ (ar | ~br)) + x[7] + 0x50a28be6, 9) + cr;
226             al = rotateLeft(al, 10);
227             ar = rotateLeft(ar, 10);
228             cl = rotateLeft(cl + (dl ^ el ^ al) + x[3], 12) + bl;
229             cr = rotateLeft(cr + (dr ^ (er | ~ar)) + x[0] + 0x50a28be6, 11) + br;
230             el = rotateLeft(el, 10);
231             er = rotateLeft(er, 10);
232             bl = rotateLeft(bl + (cl ^ dl ^ el) + x[4], 5) + al;
233             br = rotateLeft(br + (cr ^ (dr | ~er)) + x[9] + 0x50a28be6, 13) + ar;
234             dl = rotateLeft(dl, 10);
235             dr = rotateLeft(dr, 10);
236             al = rotateLeft(al + (bl ^ cl ^ dl) + x[5], 8) + el;
237             ar = rotateLeft(ar + (br ^ (cr | ~dr)) + x[2] + 0x50a28be6, 15) + er;
238             cl = rotateLeft(cl, 10);
239             cr = rotateLeft(cr, 10);
240             el = rotateLeft(el + (al ^ bl ^ cl) + x[6], 7) + dl;
241             er = rotateLeft(er + (ar ^ (br | ~cr)) + x[11] + 0x50a28be6, 15) + dr;
242             bl = rotateLeft(bl, 10);
243             br = rotateLeft(br, 10);
244             dl = rotateLeft(dl + (el ^ al ^ bl) + x[7], 9) + cl;
245             dr = rotateLeft(dr + (er ^ (ar | ~br)) + x[4] + 0x50a28be6, 5) + cr;
246             al = rotateLeft(al, 10);
247             ar = rotateLeft(ar, 10);
248             cl = rotateLeft(cl + (dl ^ el ^ al) + x[8], 11) + bl;
249             cr = rotateLeft(cr + (dr ^ (er | ~ar)) + x[13] + 0x50a28be6, 7) + br;
250             el = rotateLeft(el, 10);
251             er = rotateLeft(er, 10);
252             bl = rotateLeft(bl + (cl ^ dl ^ el) + x[9], 13) + al;
253             br = rotateLeft(br + (cr ^ (dr | ~er)) + x[6] + 0x50a28be6, 7) + ar;
254             dl = rotateLeft(dl, 10);
255             dr = rotateLeft(dr, 10);
256             al = rotateLeft(al + (bl ^ cl ^ dl) + x[10], 14) + el;
257             ar = rotateLeft(ar + (br ^ (cr | ~dr)) + x[15] + 0x50a28be6, 8) + er;
258             cl = rotateLeft(cl, 10);
259             cr = rotateLeft(cr, 10);
260             el = rotateLeft(el + (al ^ bl ^ cl) + x[11], 15) + dl;
261             er = rotateLeft(er + (ar ^ (br | ~cr)) + x[8] + 0x50a28be6, 11) + dr;
262             bl = rotateLeft(bl, 10);
263             br = rotateLeft(br, 10);
264             dl = rotateLeft(dl + (el ^ al ^ bl) + x[12], 6) + cl;
265             dr = rotateLeft(dr + (er ^ (ar | ~br)) + x[1] + 0x50a28be6, 14) + cr;
266             al = rotateLeft(al, 10);
267             ar = rotateLeft(ar, 10);
268             cl = rotateLeft(cl + (dl ^ el ^ al) + x[13], 7) + bl;
269             cr = rotateLeft(cr + (dr ^ (er | ~ar)) + x[10] + 0x50a28be6, 14) + br;
270             el = rotateLeft(el, 10);
271             er = rotateLeft(er, 10);
272             bl = rotateLeft(bl + (cl ^ dl ^ el) + x[14], 9) + al;
273             br = rotateLeft(br + (cr ^ (dr | ~er)) + x[3] + 0x50a28be6, 12) + ar;
274             dl = rotateLeft(dl, 10);
275             dr = rotateLeft(dr, 10);
276             al = rotateLeft(al + (bl ^ cl ^ dl) + x[15], 8) + el;
277             ar = rotateLeft(ar + (br ^ (cr | ~dr)) + x[12] + 0x50a28be6, 6) + er;
278             cl = rotateLeft(cl, 10);
279             cr = rotateLeft(cr, 10);
280 
281             // Round 2 and parallel round 2
282             el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[7] + 0x5a827999, 7) + dl;
283             er = rotateLeft(er + ((ar & cr) | (br & ~cr)) + x[6] + 0x5c4dd124, 9) + dr;
284             bl = rotateLeft(bl, 10);
285             br = rotateLeft(br, 10);
286             dl = rotateLeft(dl + (((al ^ bl) & el) ^ bl) + x[4] + 0x5a827999, 6) + cl;
287             dr = rotateLeft(dr + ((er & br) | (ar & ~br)) + x[11] + 0x5c4dd124, 13) + cr;
288             al = rotateLeft(al, 10);
289             ar = rotateLeft(ar, 10);
290             cl = rotateLeft(cl + (((el ^ al) & dl) ^ al) + x[13] + 0x5a827999, 8) + bl;
291             cr = rotateLeft(cr + ((dr & ar) | (er & ~ar)) + x[3] + 0x5c4dd124, 15) + br;
292             el = rotateLeft(el, 10);
293             er = rotateLeft(er, 10);
294             bl = rotateLeft(bl + (((dl ^ el) & cl) ^ el) + x[1] + 0x5a827999, 13) + al;
295             br = rotateLeft(br + ((cr & er) | (dr & ~er)) + x[7] + 0x5c4dd124, 7) + ar;
296             dl = rotateLeft(dl, 10);
297             dr = rotateLeft(dr, 10);
298             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[10] + 0x5a827999, 11) + el;
299             ar = rotateLeft(ar + ((br & dr) | (cr & ~dr)) + x[0] + 0x5c4dd124, 12) + er;
300             cl = rotateLeft(cl, 10);
301             cr = rotateLeft(cr, 10);
302             el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[6] + 0x5a827999, 9) + dl;
303             er = rotateLeft(er + ((ar & cr) | (br & ~cr)) + x[13] + 0x5c4dd124, 8) + dr;
304             bl = rotateLeft(bl, 10);
305             br = rotateLeft(br, 10);
306             dl = rotateLeft(dl + (((al ^ bl) & el) ^ bl) + x[15] + 0x5a827999, 7) + cl;
307             dr = rotateLeft(dr + ((er & br) | (ar & ~br)) + x[5] + 0x5c4dd124, 9) + cr;
308             al = rotateLeft(al, 10);
309             ar = rotateLeft(ar, 10);
310             cl = rotateLeft(cl + (((el ^ al) & dl) ^ al) + x[3] + 0x5a827999, 15) + bl;
311             cr = rotateLeft(cr + ((dr & ar) | (er & ~ar)) + x[10] + 0x5c4dd124, 11) + br;
312             el = rotateLeft(el, 10);
313             er = rotateLeft(er, 10);
314             bl = rotateLeft(bl + (((dl ^ el) & cl) ^ el) + x[12] + 0x5a827999, 7) + al;
315             br = rotateLeft(br + ((cr & er) | (dr & ~er)) + x[14] + 0x5c4dd124, 7) + ar;
316             dl = rotateLeft(dl, 10);
317             dr = rotateLeft(dr, 10);
318             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[0] + 0x5a827999, 12) + el;
319             ar = rotateLeft(ar + ((br & dr) | (cr & ~dr)) + x[15] + 0x5c4dd124, 7) + er;
320             cl = rotateLeft(cl, 10);
321             cr = rotateLeft(cr, 10);
322             el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[9] + 0x5a827999, 15) + dl;
323             er = rotateLeft(er + ((ar & cr) | (br & ~cr)) + x[8] + 0x5c4dd124, 12) + dr;
324             bl = rotateLeft(bl, 10);
325             br = rotateLeft(br, 10);
326             dl = rotateLeft(dl + (((al ^ bl) & el) ^ bl) + x[5] + 0x5a827999, 9) + cl;
327             dr = rotateLeft(dr + ((er & br) | (ar & ~br)) + x[12] + 0x5c4dd124, 7) + cr;
328             al = rotateLeft(al, 10);
329             ar = rotateLeft(ar, 10);
330             cl = rotateLeft(cl + (((el ^ al) & dl) ^ al) + x[2] + 0x5a827999, 11) + bl;
331             cr = rotateLeft(cr + ((dr & ar) | (er & ~ar)) + x[4] + 0x5c4dd124, 6) + br;
332             el = rotateLeft(el, 10);
333             er = rotateLeft(er, 10);
334             bl = rotateLeft(bl + (((dl ^ el) & cl) ^ el) + x[14] + 0x5a827999, 7) + al;
335             br = rotateLeft(br + ((cr & er) | (dr & ~er)) + x[9] + 0x5c4dd124, 15) + ar;
336             dl = rotateLeft(dl, 10);
337             dr = rotateLeft(dr, 10);
338             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[11] + 0x5a827999, 13) + el;
339             ar = rotateLeft(ar + ((br & dr) | (cr & ~dr)) + x[1] + 0x5c4dd124, 13) + er;
340             cl = rotateLeft(cl, 10);
341             cr = rotateLeft(cr, 10);
342             el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[8] + 0x5a827999, 12) + dl;
343             er = rotateLeft(er + ((ar & cr) | (br & ~cr)) + x[2] + 0x5c4dd124, 11) + dr;
344             bl = rotateLeft(bl, 10);
345             br = rotateLeft(br, 10);
346 
347             // Round 3 and parallel round 3
348             dl = rotateLeft(dl + ((el | ~al) ^ bl) + x[3] + 0x6ed9eba1, 11) + cl;
349             dr = rotateLeft(dr + ((er | ~ar) ^ br) + x[15] + 0x6d703ef3, 9) + cr;
350             al = rotateLeft(al, 10);
351             ar = rotateLeft(ar, 10);
352             cl = rotateLeft(cl + ((dl | ~el) ^ al) + x[10] + 0x6ed9eba1, 13) + bl;
353             cr = rotateLeft(cr + ((dr | ~er) ^ ar) + x[5] + 0x6d703ef3, 7) + br;
354             el = rotateLeft(el, 10);
355             er = rotateLeft(er, 10);
356             bl = rotateLeft(bl + ((cl | ~dl) ^ el) + x[14] + 0x6ed9eba1, 6) + al;
357             br = rotateLeft(br + ((cr | ~dr) ^ er) + x[1] + 0x6d703ef3, 15) + ar;
358             dl = rotateLeft(dl, 10);
359             dr = rotateLeft(dr, 10);
360             al = rotateLeft(al + ((bl | ~cl) ^ dl) + x[4] + 0x6ed9eba1, 7) + el;
361             ar = rotateLeft(ar + ((br | ~cr) ^ dr) + x[3] + 0x6d703ef3, 11) + er;
362             cl = rotateLeft(cl, 10);
363             cr = rotateLeft(cr, 10);
364             el = rotateLeft(el + ((al | ~bl) ^ cl) + x[9] + 0x6ed9eba1, 14) + dl;
365             er = rotateLeft(er + ((ar | ~br) ^ cr) + x[7] + 0x6d703ef3, 8) + dr;
366             bl = rotateLeft(bl, 10);
367             br = rotateLeft(br, 10);
368             dl = rotateLeft(dl + ((el | ~al) ^ bl) + x[15] + 0x6ed9eba1, 9) + cl;
369             dr = rotateLeft(dr + ((er | ~ar) ^ br) + x[14] + 0x6d703ef3, 6) + cr;
370             al = rotateLeft(al, 10);
371             ar = rotateLeft(ar, 10);
372             cl = rotateLeft(cl + ((dl | ~el) ^ al) + x[8] + 0x6ed9eba1, 13) + bl;
373             cr = rotateLeft(cr + ((dr | ~er) ^ ar) + x[6] + 0x6d703ef3, 6) + br;
374             el = rotateLeft(el, 10);
375             er = rotateLeft(er, 10);
376             bl = rotateLeft(bl + ((cl | ~dl) ^ el) + x[1] + 0x6ed9eba1, 15) + al;
377             br = rotateLeft(br + ((cr | ~dr) ^ er) + x[9] + 0x6d703ef3, 14) + ar;
378             dl = rotateLeft(dl, 10);
379             dr = rotateLeft(dr, 10);
380             al = rotateLeft(al + ((bl | ~cl) ^ dl) + x[2] + 0x6ed9eba1, 14) + el;
381             ar = rotateLeft(ar + ((br | ~cr) ^ dr) + x[11] + 0x6d703ef3, 12) + er;
382             cl = rotateLeft(cl, 10);
383             cr = rotateLeft(cr, 10);
384             el = rotateLeft(el + ((al | ~bl) ^ cl) + x[7] + 0x6ed9eba1, 8) + dl;
385             er = rotateLeft(er + ((ar | ~br) ^ cr) + x[8] + 0x6d703ef3, 13) + dr;
386             bl = rotateLeft(bl, 10);
387             br = rotateLeft(br, 10);
388             dl = rotateLeft(dl + ((el | ~al) ^ bl) + x[0] + 0x6ed9eba1, 13) + cl;
389             dr = rotateLeft(dr + ((er | ~ar) ^ br) + x[12] + 0x6d703ef3, 5) + cr;
390             al = rotateLeft(al, 10);
391             ar = rotateLeft(ar, 10);
392             cl = rotateLeft(cl + ((dl | ~el) ^ al) + x[6] + 0x6ed9eba1, 6) + bl;
393             cr = rotateLeft(cr + ((dr | ~er) ^ ar) + x[2] + 0x6d703ef3, 14) + br;
394             el = rotateLeft(el, 10);
395             er = rotateLeft(er, 10);
396             bl = rotateLeft(bl + ((cl | ~dl) ^ el) + x[13] + 0x6ed9eba1, 5) + al;
397             br = rotateLeft(br + ((cr | ~dr) ^ er) + x[10] + 0x6d703ef3, 13) + ar;
398             dl = rotateLeft(dl, 10);
399             dr = rotateLeft(dr, 10);
400             al = rotateLeft(al + ((bl | ~cl) ^ dl) + x[11] + 0x6ed9eba1, 12) + el;
401             ar = rotateLeft(ar + ((br | ~cr) ^ dr) + x[0] + 0x6d703ef3, 13) + er;
402             cl = rotateLeft(cl, 10);
403             cr = rotateLeft(cr, 10);
404             el = rotateLeft(el + ((al | ~bl) ^ cl) + x[5] + 0x6ed9eba1, 7) + dl;
405             er = rotateLeft(er + ((ar | ~br) ^ cr) + x[4] + 0x6d703ef3, 7) + dr;
406             bl = rotateLeft(bl, 10);
407             br = rotateLeft(br, 10);
408             dl = rotateLeft(dl + ((el | ~al) ^ bl) + x[12] + 0x6ed9eba1, 5) + cl;
409             dr = rotateLeft(dr + ((er | ~ar) ^ br) + x[13] + 0x6d703ef3, 5) + cr;
410             al = rotateLeft(al, 10);
411             ar = rotateLeft(ar, 10);
412 
413             // Round 4 and parallel round 4
414             cl = rotateLeft(cl + ((dl & al) | (el & ~al)) + x[1] + 0x8f1bbcdc, 11) + bl;
415             cr = rotateLeft(cr + (((er ^ ar) & dr) ^ ar) + x[8] + 0x7a6d76e9, 15) + br;
416             el = rotateLeft(el, 10);
417             er = rotateLeft(er, 10);
418             bl = rotateLeft(bl + ((cl & el) | (dl & ~el)) + x[9] + 0x8f1bbcdc, 12) + al;
419             br = rotateLeft(br + (((dr ^ er) & cr) ^ er) + x[6] + 0x7a6d76e9, 5) + ar;
420             dl = rotateLeft(dl, 10);
421             dr = rotateLeft(dr, 10);
422             al = rotateLeft(al + ((bl & dl) | (cl & ~dl)) + x[11] + 0x8f1bbcdc, 14) + el;
423             ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[4] + 0x7a6d76e9, 8) + er;
424             cl = rotateLeft(cl, 10);
425             cr = rotateLeft(cr, 10);
426             el = rotateLeft(el + ((al & cl) | (bl & ~cl)) + x[10] + 0x8f1bbcdc, 15) + dl;
427             er = rotateLeft(er + (((br ^ cr) & ar) ^ cr) + x[1] + 0x7a6d76e9, 11) + dr;
428             bl = rotateLeft(bl, 10);
429             br = rotateLeft(br, 10);
430             dl = rotateLeft(dl + ((el & bl) | (al & ~bl)) + x[0] + 0x8f1bbcdc, 14) + cl;
431             dr = rotateLeft(dr + (((ar ^ br) & er) ^ br) + x[3] + 0x7a6d76e9, 14) + cr;
432             al = rotateLeft(al, 10);
433             ar = rotateLeft(ar, 10);
434             cl = rotateLeft(cl + ((dl & al) | (el & ~al)) + x[8] + 0x8f1bbcdc, 15) + bl;
435             cr = rotateLeft(cr + (((er ^ ar) & dr) ^ ar) + x[11] + 0x7a6d76e9, 14) + br;
436             el = rotateLeft(el, 10);
437             er = rotateLeft(er, 10);
438             bl = rotateLeft(bl + ((cl & el) | (dl & ~el)) + x[12] + 0x8f1bbcdc, 9) + al;
439             br = rotateLeft(br + (((dr ^ er) & cr) ^ er) + x[15] + 0x7a6d76e9, 6) + ar;
440             dl = rotateLeft(dl, 10);
441             dr = rotateLeft(dr, 10);
442             al = rotateLeft(al + ((bl & dl) | (cl & ~dl)) + x[4] + 0x8f1bbcdc, 8) + el;
443             ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[0] + 0x7a6d76e9, 14) + er;
444             cl = rotateLeft(cl, 10);
445             cr = rotateLeft(cr, 10);
446             el = rotateLeft(el + ((al & cl) | (bl & ~cl)) + x[13] + 0x8f1bbcdc, 9) + dl;
447             er = rotateLeft(er + (((br ^ cr) & ar) ^ cr) + x[5] + 0x7a6d76e9, 6) + dr;
448             bl = rotateLeft(bl, 10);
449             br = rotateLeft(br, 10);
450             dl = rotateLeft(dl + ((el & bl) | (al & ~bl)) + x[3] + 0x8f1bbcdc, 14) + cl;
451             dr = rotateLeft(dr + (((ar ^ br) & er) ^ br) + x[12] + 0x7a6d76e9, 9) + cr;
452             al = rotateLeft(al, 10);
453             ar = rotateLeft(ar, 10);
454             cl = rotateLeft(cl + ((dl & al) | (el & ~al)) + x[7] + 0x8f1bbcdc, 5) + bl;
455             cr = rotateLeft(cr + (((er ^ ar) & dr) ^ ar) + x[2] + 0x7a6d76e9, 12) + br;
456             el = rotateLeft(el, 10);
457             er = rotateLeft(er, 10);
458             bl = rotateLeft(bl + ((cl & el) | (dl & ~el)) + x[15] + 0x8f1bbcdc, 6) + al;
459             br = rotateLeft(br + (((dr ^ er) & cr) ^ er) + x[13] + 0x7a6d76e9, 9) + ar;
460             dl = rotateLeft(dl, 10);
461             dr = rotateLeft(dr, 10);
462             al = rotateLeft(al + ((bl & dl) | (cl & ~dl)) + x[14] + 0x8f1bbcdc, 8) + el;
463             ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[9] + 0x7a6d76e9, 12) + er;
464             cl = rotateLeft(cl, 10);
465             cr = rotateLeft(cr, 10);
466             el = rotateLeft(el + ((al & cl) | (bl & ~cl)) + x[5] + 0x8f1bbcdc, 6) + dl;
467             er = rotateLeft(er + (((br ^ cr) & ar) ^ cr) + x[7] + 0x7a6d76e9, 5) + dr;
468             bl = rotateLeft(bl, 10);
469             br = rotateLeft(br, 10);
470             dl = rotateLeft(dl + ((el & bl) | (al & ~bl)) + x[6] + 0x8f1bbcdc, 5) + cl;
471             dr = rotateLeft(dr + (((ar ^ br) & er) ^ br) + x[10] + 0x7a6d76e9, 15) + cr;
472             al = rotateLeft(al, 10);
473             ar = rotateLeft(ar, 10);
474             cl = rotateLeft(cl + ((dl & al) | (el & ~al)) + x[2] + 0x8f1bbcdc, 12) + bl;
475             cr = rotateLeft(cr + (((er ^ ar) & dr) ^ ar) + x[14] + 0x7a6d76e9, 8) + br;
476             el = rotateLeft(el, 10);
477             er = rotateLeft(er, 10);
478 
479             // Round 5 and parallel round 5
480             bl = rotateLeft(bl + (cl ^ (dl | ~el)) + x[4] + 0xa953fd4e, 9) + al;
481             br = rotateLeft(br + (cr ^ dr ^ er) + x[12], 8) + ar;
482             dl = rotateLeft(dl, 10);
483             dr = rotateLeft(dr, 10);
484             al = rotateLeft(al + (bl ^ (cl | ~dl)) + x[0] + 0xa953fd4e, 15) + el;
485             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[15], 5) + er;
486             cl = rotateLeft(cl, 10);
487             cr = rotateLeft(cr, 10);
488             el = rotateLeft(el + (al ^ (bl | ~cl)) + x[5] + 0xa953fd4e, 5) + dl;
489             er = rotateLeft(er + (ar ^ br ^ cr) + x[10], 12) + dr;
490             bl = rotateLeft(bl, 10);
491             br = rotateLeft(br, 10);
492             dl = rotateLeft(dl + (el ^ (al | ~bl)) + x[9] + 0xa953fd4e, 11) + cl;
493             dr = rotateLeft(dr + (er ^ ar ^ br) + x[4], 9) + cr;
494             al = rotateLeft(al, 10);
495             ar = rotateLeft(ar, 10);
496             cl = rotateLeft(cl + (dl ^ (el | ~al)) + x[7] + 0xa953fd4e, 6) + bl;
497             cr = rotateLeft(cr + (dr ^ er ^ ar) + x[1], 12) + br;
498             el = rotateLeft(el, 10);
499             er = rotateLeft(er, 10);
500             bl = rotateLeft(bl + (cl ^ (dl | ~el)) + x[12] + 0xa953fd4e, 8) + al;
501             br = rotateLeft(br + (cr ^ dr ^ er) + x[5], 5) + ar;
502             dl = rotateLeft(dl, 10);
503             dr = rotateLeft(dr, 10);
504             al = rotateLeft(al + (bl ^ (cl | ~dl)) + x[2] + 0xa953fd4e, 13) + el;
505             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[8], 14) + er;
506             cl = rotateLeft(cl, 10);
507             cr = rotateLeft(cr, 10);
508             el = rotateLeft(el + (al ^ (bl | ~cl)) + x[10] + 0xa953fd4e, 12) + dl;
509             er = rotateLeft(er + (ar ^ br ^ cr) + x[7], 6) + dr;
510             bl = rotateLeft(bl, 10);
511             br = rotateLeft(br, 10);
512             dl = rotateLeft(dl + (el ^ (al | ~bl)) + x[14] + 0xa953fd4e, 5) + cl;
513             dr = rotateLeft(dr + (er ^ ar ^ br) + x[6], 8) + cr;
514             al = rotateLeft(al, 10);
515             ar = rotateLeft(ar, 10);
516             cl = rotateLeft(cl + (dl ^ (el | ~al)) + x[1] + 0xa953fd4e, 12) + bl;
517             cr = rotateLeft(cr + (dr ^ er ^ ar) + x[2], 13) + br;
518             el = rotateLeft(el, 10);
519             er = rotateLeft(er, 10);
520             bl = rotateLeft(bl + (cl ^ (dl | ~el)) + x[3] + 0xa953fd4e, 13) + al;
521             br = rotateLeft(br + (cr ^ dr ^ er) + x[13], 6) + ar;
522             dl = rotateLeft(dl, 10);
523             dr = rotateLeft(dr, 10);
524             al = rotateLeft(al + (bl ^ (cl | ~dl)) + x[8] + 0xa953fd4e, 14) + el;
525             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[14], 5) + er;
526             cl = rotateLeft(cl, 10);
527             cr = rotateLeft(cr, 10);
528             el = rotateLeft(el + (al ^ (bl | ~cl)) + x[11] + 0xa953fd4e, 11) + dl;
529             er = rotateLeft(er + (ar ^ br ^ cr) + x[0], 15) + dr;
530             bl = rotateLeft(bl, 10);
531             br = rotateLeft(br, 10);
532             dl = rotateLeft(dl + (el ^ (al | ~bl)) + x[6] + 0xa953fd4e, 8) + cl;
533             dr = rotateLeft(dr + (er ^ ar ^ br) + x[3], 13) + cr;
534             al = rotateLeft(al, 10);
535             ar = rotateLeft(ar, 10);
536             cl = rotateLeft(cl + (dl ^ (el | ~al)) + x[15] + 0xa953fd4e, 5) + bl;
537             cr = rotateLeft(cr + (dr ^ er ^ ar) + x[9], 11) + br;
538             el = rotateLeft(el, 10);
539             er = rotateLeft(er, 10);
540             bl = rotateLeft(bl + (cl ^ (dl | ~el)) + x[13] + 0xa953fd4e, 6) + al;
541             br = rotateLeft(br + (cr ^ dr ^ er) + x[11], 11) + ar;
542             dl = rotateLeft(dl, 10);
543             dr = rotateLeft(dr, 10);
544 
545             uint t = context[1] + cl + dr;
546             context[1] = context[2] + dl + er;
547             context[2] = context[3] + el + ar;
548             context[3] = context[4] + al + br;
549             context[4] = context[0] + bl + cr;
550             context[0] = t;
551 
552             x[] = 0;
553         }
554 }
555 
556 /*******************************************************************************
557 
558 *******************************************************************************/
559 
560 unittest
561 {
562     static istring[] strings = [
563             "",
564             "a",
565             "abc",
566             "message digest",
567             "abcdefghijklmnopqrstuvwxyz",
568             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
569             "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
570             "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
571     ];
572 
573     static istring[] results = [
574             "9c1185a5c5e9fc54612808977ee8f548b2258d31",
575             "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe",
576             "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc",
577             "5d0689ef49d2fae572b881b123a85ffa21595f36",
578             "f71c27109c692c1b56bbdceb5b9d2865b3708dbc",
579             "12a053384a9c0c88e405a06c27dcf49ada62eb2b",
580             "b0e20b6e3116640286ed3a87a5713079b21f5189",
581             "9b752e45573d4b39f4dbd3323cab82bf63326bfb"
582     ];
583 
584     Ripemd160 h = new Ripemd160();
585 
586     foreach (i, s; strings)
587     {
588         h.update(cast(ubyte[]) s);
589         char[] d = h.hexDigest;
590 
591         test(d == results[i],":("~s~")("~d~")!=("~results[i]~")");
592     }
593 
594 
595     char[] s = new char[1000000];
596     for (auto i = 0; i < s.length; i++) s[i] = 'a';
597     auto result = "52783243c1697bdbe16d37f97f68f08325dc1528";
598     h.update(cast(ubyte[]) s);
599     auto d = h.hexDigest;
600 
601     test(d == result,":(1 million times \"a\")("~d~")!=("~result~")");
602 }