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