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.Ripemd320;
24 
25 private import tango.util.digest.MerkleDamgard;
26 
27 public  import tango.util.digest.Digest;
28 
29 /*******************************************************************************
30 
31 *******************************************************************************/
32 
33 final class Ripemd320 : MerkleDamgard
34 {
35         private uint[10]        context;
36         private enum uint     padChar = 0x80;
37 
38         /***********************************************************************
39 
40         ***********************************************************************/
41 
42         private __gshared immutable uint[10] initial =
43         [
44 				0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0,
45 				0x76543210, 0xfedcba98, 0x89abcdef, 0x01234567, 0x3c2d1e0f
46         ];
47 
48         /***********************************************************************
49 
50         	Construct a Ripemd320
51 
52          ***********************************************************************/
53 
54         this() { }
55 
56         /***********************************************************************
57 
58         	The size of a Ripemd320 digest is 40 bytes
59         
60          ***********************************************************************/
61 
62         override uint digestSize() {return 40;}
63 
64 
65         /***********************************************************************
66 
67         	Initialize the cipher
68 
69         	Remarks:
70         		Returns the cipher state to it's initial value
71 
72          ***********************************************************************/
73 
74         override void reset()
75         {
76         	super.reset();
77         	context[] = initial[];
78         }
79 
80         /***********************************************************************
81 
82         	Obtain the digest
83 
84         	Returns:
85         		the digest
86 
87         	Remarks:
88         		Returns a digest of the current cipher state, this may be the
89         		final digest, or a digest of the state between calls to update()
90 
91          ***********************************************************************/
92 
93         override void createDigest(ubyte[] buf)
94         {
95             version (BigEndian)
96             	ByteSwap.swap32 (context.ptr, context.length * uint.sizeof);
97 
98         	buf[] = (cast(ubyte[]) context)[];
99         }
100 
101 
102         /***********************************************************************
103 
104          	block size
105 
106         	Returns:
107         	the block size
108 
109         	Remarks:
110         	Specifies the size (in bytes) of the block of data to pass to
111         	each call to transform(). For Ripemd320 the blockSize is 64.
112 
113          ***********************************************************************/
114 
115         protected override uint blockSize() { return 64; }
116 
117         /***********************************************************************
118 
119         	Length padding size
120 
121         	Returns:
122         	the length padding size
123 
124         	Remarks:
125         	Specifies the size (in bytes) of the padding which uses the
126         	length of the data which has been ciphered, this padding is
127         	carried out by the padLength method. For Ripemd320 the addSize is 8.
128 
129          ***********************************************************************/
130 
131         protected override uint addSize()   { return 8;  }
132 
133         /***********************************************************************
134 
135         	Pads the cipher data
136 
137         	Params:
138         	data = a slice of the cipher buffer to fill with padding
139 
140         	Remarks:
141         	Fills the passed buffer slice with the appropriate padding for
142         	the final call to transform(). This padding will fill the cipher
143         	buffer up to blockSize()-addSize().
144 
145          ***********************************************************************/
146 
147         protected override void padMessage(ubyte[] at)
148         {
149         	at[0] = padChar;
150         	at[1..at.length] = 0;
151         }
152 
153         /***********************************************************************
154 
155         	Performs the length padding
156 
157         	Params:
158         	data   = the slice of the cipher buffer to fill with padding
159         	length = the length of the data which has been ciphered
160 
161         	Remarks:
162         	Fills the passed buffer slice with addSize() bytes of padding
163         	based on the length in bytes of the input data which has been
164         	ciphered.
165 
166          ***********************************************************************/
167 
168         protected override void padLength(ubyte[] at, ulong length)
169         {
170         	length <<= 3;
171         	littleEndian64((cast(ubyte*)&length)[0..8],cast(ulong[]) at); 
172         }
173 
174         /***********************************************************************
175 
176         	Performs the cipher on a block of data
177 
178         	Params:
179         	data = the block of data to cipher
180 
181         	Remarks:
182         	The actual cipher algorithm is carried out by this method on
183         	the passed block of data. This method is called for every
184         	blockSize() bytes of input data and once more with the remaining
185         	data padded to blockSize().
186 
187          ***********************************************************************/
188 
189         protected override void transform(const(ubyte[]) input)
190         {
191         	uint al, bl, cl, dl, el;
192         	uint ar, br, cr, dr, er;
193             uint[16] x;
194             uint t;
195 
196             littleEndian32(input,x);
197 
198             al = context[0];
199             bl = context[1];
200             cl = context[2];
201             dl = context[3];
202             el = context[4];
203             ar = context[5];
204             br = context[6];
205             cr = context[7];
206             dr = context[8];
207             er = context[9];
208 
209             // Round 1 and parallel round 1
210             al = rotateLeft(al + (bl ^ cl ^ dl) + x[0], 11) + el;
211             ar = rotateLeft(ar + (br ^ (cr | ~(dr))) + x[5] + 0x50a28be6, 8) + er;
212             cl = rotateLeft(cl, 10);
213             cr = rotateLeft(cr, 10);
214             el = rotateLeft(el + (al ^ bl ^ cl) + x[1], 14) + dl;
215             er = rotateLeft(er + (ar ^ (br | ~(cr))) + x[14] + 0x50a28be6, 9) + dr;
216             bl = rotateLeft(bl, 10);
217             br = rotateLeft(br, 10);
218             dl = rotateLeft(dl + (el ^ al ^ bl) + x[2], 15) + cl;
219             dr = rotateLeft(dr + (er ^ (ar | ~(br))) + x[7] + 0x50a28be6, 9) + cr;
220             al = rotateLeft(al, 10);
221             ar = rotateLeft(ar, 10);
222             cl = rotateLeft(cl + (dl ^ el ^ al) + x[3], 12) + bl;
223             cr = rotateLeft(cr + (dr ^ (er | ~(ar))) + x[0] + 0x50a28be6, 11) + br;
224             el = rotateLeft(el, 10);
225             er = rotateLeft(er, 10);
226             bl = rotateLeft(bl + (cl ^ dl ^ el) + x[4], 5) + al;
227             br = rotateLeft(br + (cr ^ (dr | ~(er))) + x[9] + 0x50a28be6, 13) + ar;
228             dl = rotateLeft(dl, 10);
229             dr = rotateLeft(dr, 10);
230             al = rotateLeft(al + (bl ^ cl ^ dl) + x[5], 8) + el;
231             ar = rotateLeft(ar + (br ^ (cr | ~(dr))) + x[2] + 0x50a28be6, 15) + er;
232             cl = rotateLeft(cl, 10);
233             cr = rotateLeft(cr, 10);
234             el = rotateLeft(el + (al ^ bl ^ cl) + x[6], 7) + dl;
235             er = rotateLeft(er + (ar ^ (br | ~(cr))) + x[11] + 0x50a28be6, 15) + dr;
236             bl = rotateLeft(bl, 10);
237             br = rotateLeft(br, 10);
238             dl = rotateLeft(dl + (el ^ al ^ bl) + x[7], 9) + cl;
239             dr = rotateLeft(dr + (er ^ (ar | ~(br))) + x[4] + 0x50a28be6, 5) + cr;
240             al = rotateLeft(al, 10);
241             ar = rotateLeft(ar, 10);
242             cl = rotateLeft(cl + (dl ^ el ^ al) + x[8], 11) + bl;
243             cr = rotateLeft(cr + (dr ^ (er | ~(ar))) + x[13] + 0x50a28be6, 7) + br;
244             el = rotateLeft(el, 10);
245             er = rotateLeft(er, 10);
246             bl = rotateLeft(bl + (cl ^ dl ^ el) + x[9], 13) + al;
247             br = rotateLeft(br + (cr ^ (dr | ~(er))) + x[6] + 0x50a28be6, 7) + ar;
248             dl = rotateLeft(dl, 10);
249             dr = rotateLeft(dr, 10);
250             al = rotateLeft(al + (bl ^ cl ^ dl) + x[10], 14) + el;
251             ar = rotateLeft(ar + (br ^ (cr | ~(dr))) + x[15] + 0x50a28be6, 8) + er;
252             cl = rotateLeft(cl, 10);
253             cr = rotateLeft(cr, 10);
254             el = rotateLeft(el + (al ^ bl ^ cl) + x[11], 15) + dl;
255             er = rotateLeft(er + (ar ^ (br | ~(cr))) + x[8] + 0x50a28be6, 11) + dr;
256             bl = rotateLeft(bl, 10);
257             br = rotateLeft(br, 10);
258             dl = rotateLeft(dl + (el ^ al ^ bl) + x[12], 6) + cl;
259             dr = rotateLeft(dr + (er ^ (ar | ~(br))) + x[1] + 0x50a28be6, 14) + cr;
260             al = rotateLeft(al, 10);
261             ar = rotateLeft(ar, 10);
262             cl = rotateLeft(cl + (dl ^ el ^ al) + x[13], 7) + bl;
263             cr = rotateLeft(cr + (dr ^ (er | ~(ar))) + x[10] + 0x50a28be6, 14) + br;
264             el = rotateLeft(el, 10);
265             er = rotateLeft(er, 10);
266             bl = rotateLeft(bl + (cl ^ dl ^ el) + x[14], 9) + al;
267             br = rotateLeft(br + (cr ^ (dr | ~(er))) + x[3] + 0x50a28be6, 12) + ar;
268             dl = rotateLeft(dl, 10);
269             dr = rotateLeft(dr, 10);
270             al = rotateLeft(al + (bl ^ cl ^ dl) + x[15], 8) + el;
271             ar = rotateLeft(ar + (br ^ (cr | ~(dr))) + x[12] + 0x50a28be6, 6) + er;
272             cl = rotateLeft(cl, 10);
273             cr = rotateLeft(cr, 10);
274             
275             t = al; al = ar; ar = t;
276             
277             // Round 2 and parallel round 2
278             el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[7] + 0x5a827999, 7) + dl;
279             er = rotateLeft(er + ((ar & cr) | (br & ~(cr))) + x[6] + 0x5c4dd124, 9) + dr;
280             bl = rotateLeft(bl, 10);
281             br = rotateLeft(br, 10);
282             dl = rotateLeft(dl + (((al ^ bl) & el) ^ bl) + x[4] + 0x5a827999, 6) + cl;
283             dr = rotateLeft(dr + ((er & br) | (ar & ~(br))) + x[11] + 0x5c4dd124, 13) + cr;
284             al = rotateLeft(al, 10);
285             ar = rotateLeft(ar, 10);
286             cl = rotateLeft(cl + (((el ^ al) & dl) ^ al) + x[13] + 0x5a827999, 8) + bl;
287             cr = rotateLeft(cr + ((dr & ar) | (er & ~(ar))) + x[3] + 0x5c4dd124, 15) + br;
288             el = rotateLeft(el, 10);
289             er = rotateLeft(er, 10);
290             bl = rotateLeft(bl + (((dl ^ el) & cl) ^ el) + x[1] + 0x5a827999, 13) + al;
291             br = rotateLeft(br + ((cr & er) | (dr & ~(er))) + x[7] + 0x5c4dd124, 7) + ar;
292             dl = rotateLeft(dl, 10);
293             dr = rotateLeft(dr, 10);
294             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[10] + 0x5a827999, 11) + el;
295             ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[0] + 0x5c4dd124, 12) + er;
296             cl = rotateLeft(cl, 10);
297             cr = rotateLeft(cr, 10);
298             el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[6] + 0x5a827999, 9) + dl;
299             er = rotateLeft(er + ((ar & cr) | (br & ~(cr))) + x[13] + 0x5c4dd124, 8) + dr;
300             bl = rotateLeft(bl, 10);
301             br = rotateLeft(br, 10);
302             dl = rotateLeft(dl + (((al ^ bl) & el) ^ bl) + x[15] + 0x5a827999, 7) + cl;
303             dr = rotateLeft(dr + ((er & br) | (ar & ~(br))) + x[5] + 0x5c4dd124, 9) + cr;
304             al = rotateLeft(al, 10);
305             ar = rotateLeft(ar, 10);
306             cl = rotateLeft(cl + (((el ^ al) & dl) ^ al) + x[3] + 0x5a827999, 15) + bl;
307             cr = rotateLeft(cr + ((dr & ar) | (er & ~(ar))) + x[10] + 0x5c4dd124, 11) + br;
308             el = rotateLeft(el, 10);
309             er = rotateLeft(er, 10);
310             bl = rotateLeft(bl + (((dl ^ el) & cl) ^ el) + x[12] + 0x5a827999, 7) + al;
311             br = rotateLeft(br + ((cr & er) | (dr & ~(er))) + x[14] + 0x5c4dd124, 7) + ar;
312             dl = rotateLeft(dl, 10);
313             dr = rotateLeft(dr, 10);
314             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[0] + 0x5a827999, 12) + el;
315             ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[15] + 0x5c4dd124, 7) + er;
316             cl = rotateLeft(cl, 10);
317             cr = rotateLeft(cr, 10);
318             el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[9] + 0x5a827999, 15) + dl;
319             er = rotateLeft(er + ((ar & cr) | (br & ~(cr))) + x[8] + 0x5c4dd124, 12) + dr;
320             bl = rotateLeft(bl, 10);
321             br = rotateLeft(br, 10);
322             dl = rotateLeft(dl + (((al ^ bl) & el) ^ bl) + x[5] + 0x5a827999, 9) + cl;
323             dr = rotateLeft(dr + ((er & br) | (ar & ~(br))) + x[12] + 0x5c4dd124, 7) + cr;
324             al = rotateLeft(al, 10);
325             ar = rotateLeft(ar, 10);
326             cl = rotateLeft(cl + (((el ^ al) & dl) ^ al) + x[2] + 0x5a827999, 11) + bl;
327             cr = rotateLeft(cr + ((dr & ar) | (er & ~(ar))) + x[4] + 0x5c4dd124, 6) + br;
328             el = rotateLeft(el, 10);
329             er = rotateLeft(er, 10);
330             bl = rotateLeft(bl + (((dl ^ el) & cl) ^ el) + x[14] + 0x5a827999, 7) + al;
331             br = rotateLeft(br + ((cr & er) | (dr & ~(er))) + x[9] + 0x5c4dd124, 15) + ar;
332             dl = rotateLeft(dl, 10);
333             dr = rotateLeft(dr, 10);
334             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[11] + 0x5a827999, 13) + el;
335             ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[1] + 0x5c4dd124, 13) + er;
336             cl = rotateLeft(cl, 10);
337             cr = rotateLeft(cr, 10);
338             el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[8] + 0x5a827999, 12) + dl;
339             er = rotateLeft(er + ((ar & cr) | (br & ~(cr))) + x[2] + 0x5c4dd124, 11) + dr;
340             bl = rotateLeft(bl, 10);
341             br = rotateLeft(br, 10);
342             
343             t = bl; bl = br; br = t;
344             
345             // Round 3 and parallel round 3
346             dl = rotateLeft(dl + ((el | ~(al)) ^ bl) + x[3] + 0x6ed9eba1, 11) + cl;
347             dr = rotateLeft(dr + ((er | ~(ar)) ^ br) + x[15] + 0x6d703ef3, 9) + cr;
348             al = rotateLeft(al, 10);
349             ar = rotateLeft(ar, 10);
350             cl = rotateLeft(cl + ((dl | ~(el)) ^ al) + x[10] + 0x6ed9eba1, 13) + bl;
351             cr = rotateLeft(cr + ((dr | ~(er)) ^ ar) + x[5] + 0x6d703ef3, 7) + br;
352             el = rotateLeft(el, 10);
353             er = rotateLeft(er, 10);
354             bl = rotateLeft(bl + ((cl | ~(dl)) ^ el) + x[14] + 0x6ed9eba1, 6) + al;
355             br = rotateLeft(br + ((cr | ~(dr)) ^ er) + x[1] + 0x6d703ef3, 15) + ar;
356             dl = rotateLeft(dl, 10);
357             dr = rotateLeft(dr, 10);
358             al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[4] + 0x6ed9eba1, 7) + el;
359             ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[3] + 0x6d703ef3, 11) + er;
360             cl = rotateLeft(cl, 10);
361             cr = rotateLeft(cr, 10);
362             el = rotateLeft(el + ((al | ~(bl)) ^ cl) + x[9] + 0x6ed9eba1, 14) + dl;
363             er = rotateLeft(er + ((ar | ~(br)) ^ cr) + x[7] + 0x6d703ef3, 8) + dr;
364             bl = rotateLeft(bl, 10);
365             br = rotateLeft(br, 10);
366             dl = rotateLeft(dl + ((el | ~(al)) ^ bl) + x[15] + 0x6ed9eba1, 9) + cl;
367             dr = rotateLeft(dr + ((er | ~(ar)) ^ br) + x[14] + 0x6d703ef3, 6) + cr;
368             al = rotateLeft(al, 10);
369             ar = rotateLeft(ar, 10);
370             cl = rotateLeft(cl + ((dl | ~(el)) ^ al) + x[8] + 0x6ed9eba1, 13) + bl;
371             cr = rotateLeft(cr + ((dr | ~(er)) ^ ar) + x[6] + 0x6d703ef3, 6) + br;
372             el = rotateLeft(el, 10);
373             er = rotateLeft(er, 10);
374             bl = rotateLeft(bl + ((cl | ~(dl)) ^ el) + x[1] + 0x6ed9eba1, 15) + al;
375             br = rotateLeft(br + ((cr | ~(dr)) ^ er) + x[9] + 0x6d703ef3, 14) + ar;
376             dl = rotateLeft(dl, 10);
377             dr = rotateLeft(dr, 10);
378             al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[2] + 0x6ed9eba1, 14) + el;
379             ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[11] + 0x6d703ef3, 12) + er;
380             cl = rotateLeft(cl, 10);
381             cr = rotateLeft(cr, 10);
382             el = rotateLeft(el + ((al | ~(bl)) ^ cl) + x[7] + 0x6ed9eba1, 8) + dl;
383             er = rotateLeft(er + ((ar | ~(br)) ^ cr) + x[8] + 0x6d703ef3, 13) + dr;
384             bl = rotateLeft(bl, 10);
385             br = rotateLeft(br, 10);
386             dl = rotateLeft(dl + ((el | ~(al)) ^ bl) + x[0] + 0x6ed9eba1, 13) + cl;
387             dr = rotateLeft(dr + ((er | ~(ar)) ^ br) + x[12] + 0x6d703ef3, 5) + cr;
388             al = rotateLeft(al, 10);
389             ar = rotateLeft(ar, 10);
390             cl = rotateLeft(cl + ((dl | ~(el)) ^ al) + x[6] + 0x6ed9eba1, 6) + bl;
391             cr = rotateLeft(cr + ((dr | ~(er)) ^ ar) + x[2] + 0x6d703ef3, 14) + br;
392             el = rotateLeft(el, 10);
393             er = rotateLeft(er, 10);
394             bl = rotateLeft(bl + ((cl | ~(dl)) ^ el) + x[13] + 0x6ed9eba1, 5) + al;
395             br = rotateLeft(br + ((cr | ~(dr)) ^ er) + x[10] + 0x6d703ef3, 13) + ar;
396             dl = rotateLeft(dl, 10);
397             dr = rotateLeft(dr, 10);
398             al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[11] + 0x6ed9eba1, 12) + el;
399             ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[0] + 0x6d703ef3, 13) + er;
400             cl = rotateLeft(cl, 10);
401             cr = rotateLeft(cr, 10);
402             el = rotateLeft(el + ((al | ~(bl)) ^ cl) + x[5] + 0x6ed9eba1, 7) + dl;
403             er = rotateLeft(er + ((ar | ~(br)) ^ cr) + x[4] + 0x6d703ef3, 7) + dr;
404             bl = rotateLeft(bl, 10);
405             br = rotateLeft(br, 10);
406             dl = rotateLeft(dl + ((el | ~(al)) ^ bl) + x[12] + 0x6ed9eba1, 5) + cl;
407             dr = rotateLeft(dr + ((er | ~(ar)) ^ br) + x[13] + 0x6d703ef3, 5) + cr;
408             al = rotateLeft(al, 10);
409             ar = rotateLeft(ar, 10);
410             
411             t = cl; cl = cr; cr = t;
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             t = dl; dl = dr; dr = t;
480             
481             // Round 5 and parallel round 5
482             bl = rotateLeft(bl + (cl ^ (dl | ~(el))) + x[4] + 0xa953fd4e, 9) + al;
483             br = rotateLeft(br + (cr ^ dr ^ er) + x[12], 8) + ar;
484             dl = rotateLeft(dl, 10);
485             dr = rotateLeft(dr, 10);
486             al = rotateLeft(al + (bl ^ (cl | ~(dl))) + x[0] + 0xa953fd4e, 15) + el;
487             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[15], 5) + er;
488             cl = rotateLeft(cl, 10);
489             cr = rotateLeft(cr, 10);
490             el = rotateLeft(el + (al ^ (bl | ~(cl))) + x[5] + 0xa953fd4e, 5) + dl;
491             er = rotateLeft(er + (ar ^ br ^ cr) + x[10], 12) + dr;
492             bl = rotateLeft(bl, 10);
493             br = rotateLeft(br, 10);
494             dl = rotateLeft(dl + (el ^ (al | ~(bl))) + x[9] + 0xa953fd4e, 11) + cl;
495             dr = rotateLeft(dr + (er ^ ar ^ br) + x[4], 9) + cr;
496             al = rotateLeft(al, 10);
497             ar = rotateLeft(ar, 10);
498             cl = rotateLeft(cl + (dl ^ (el | ~(al))) + x[7] + 0xa953fd4e, 6) + bl;
499             cr = rotateLeft(cr + (dr ^ er ^ ar) + x[1], 12) + br;
500             el = rotateLeft(el, 10);
501             er = rotateLeft(er, 10);
502             bl = rotateLeft(bl + (cl ^ (dl | ~(el))) + x[12] + 0xa953fd4e, 8) + al;
503             br = rotateLeft(br + (cr ^ dr ^ er) + x[5], 5) + ar;
504             dl = rotateLeft(dl, 10);
505             dr = rotateLeft(dr, 10);
506             al = rotateLeft(al + (bl ^ (cl | ~(dl))) + x[2] + 0xa953fd4e, 13) + el;
507             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[8], 14) + er;
508             cl = rotateLeft(cl, 10);
509             cr = rotateLeft(cr, 10);
510             el = rotateLeft(el + (al ^ (bl | ~(cl))) + x[10] + 0xa953fd4e, 12) + dl;
511             er = rotateLeft(er + (ar ^ br ^ cr) + x[7], 6) + dr;
512             bl = rotateLeft(bl, 10);
513             br = rotateLeft(br, 10);
514             dl = rotateLeft(dl + (el ^ (al | ~(bl))) + x[14] + 0xa953fd4e, 5) + cl;
515             dr = rotateLeft(dr + (er ^ ar ^ br) + x[6], 8) + cr;
516             al = rotateLeft(al, 10);
517             ar = rotateLeft(ar, 10);
518             cl = rotateLeft(cl + (dl ^ (el | ~(al))) + x[1] + 0xa953fd4e, 12) + bl;
519             cr = rotateLeft(cr + (dr ^ er ^ ar) + x[2], 13) + br;
520             el = rotateLeft(el, 10);
521             er = rotateLeft(er, 10);
522             bl = rotateLeft(bl + (cl ^ (dl | ~(el))) + x[3] + 0xa953fd4e, 13) + al;
523             br = rotateLeft(br + (cr ^ dr ^ er) + x[13], 6) + ar;
524             dl = rotateLeft(dl, 10);
525             dr = rotateLeft(dr, 10);
526             al = rotateLeft(al + (bl ^ (cl | ~(dl))) + x[8] + 0xa953fd4e, 14) + el;
527             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[14], 5) + er;
528             cl = rotateLeft(cl, 10);
529             cr = rotateLeft(cr, 10);
530             el = rotateLeft(el + (al ^ (bl | ~(cl))) + x[11] + 0xa953fd4e, 11) + dl;
531             er = rotateLeft(er + (ar ^ br ^ cr) + x[0], 15) + dr;
532             bl = rotateLeft(bl, 10);
533             br = rotateLeft(br, 10);
534             dl = rotateLeft(dl + (el ^ (al | ~(bl))) + x[6] + 0xa953fd4e, 8) + cl;
535             dr = rotateLeft(dr + (er ^ ar ^ br) + x[3], 13) + cr;
536             al = rotateLeft(al, 10);
537             ar = rotateLeft(ar, 10);
538             cl = rotateLeft(cl + (dl ^ (el | ~(al))) + x[15] + 0xa953fd4e, 5) + bl;
539             cr = rotateLeft(cr + (dr ^ er ^ ar) + x[9], 11) + br;
540             el = rotateLeft(el, 10);
541             er = rotateLeft(er, 10);
542             bl = rotateLeft(bl + (cl ^ (dl | ~(el))) + x[13] + 0xa953fd4e, 6) + al;
543             br = rotateLeft(br + (cr ^ dr ^ er) + x[11], 11) + ar;
544             dl = rotateLeft(dl, 10);
545             dr = rotateLeft(dr, 10);
546             
547             // Do not swap el and er; simply add the right value to context 
548 
549             context[0] += al;
550             context[1] += bl;
551             context[2] += cl;
552             context[3] += dl;
553             context[4] += er;
554             context[5] += ar;
555             context[6] += br;
556             context[7] += cr;
557             context[8] += dr;
558             context[9] += el;
559 
560             x[] = 0;
561         }
562 
563 }
564 
565 /*******************************************************************************
566 
567 *******************************************************************************/
568 
569 debug(UnitTest)
570 {
571     unittest
572     {
573     __gshared immutable immutable(char)[][] strings =
574     [
575             "",
576             "a",
577             "abc",
578             "message digest",
579             "abcdefghijklmnopqrstuvwxyz",
580             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
581             "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
582             "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
583     ];
584 
585     __gshared immutable immutable(char)[][] results =
586     [
587             "22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8",
588             "ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d",
589             "de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d",
590             "3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197",
591             "cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009",
592             "d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac",
593             "ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4",
594             "557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42"
595     ];
596 
597     Ripemd320 h = new Ripemd320();
598 
599     foreach (int i, immutable(char)[] s; strings)
600             {
601             h.update(cast(ubyte[]) s);
602             char[] d = h.hexDigest();
603 
604             assert(d == results[i],":("~s~")("~d~")!=("~results[i]~")");
605             }
606 
607     
608     char[] s = new char[1000000];
609     for (auto i = 0; i < s.length; i++) s[i] = 'a';
610     immutable(char)[] result = "bdee37f4371e20646b8b0d862dda16292ae36f40965e8c8509e63d1dbddecc503e2b63eb9245bb66";
611     h.update(cast(ubyte[]) s);
612     char[] d = h.hexDigest();
613 
614     assert(d == result,":(1 million times \"a\")("~d~")!=("~result~")");
615     }
616 	
617 }