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 Ripemd256 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.Ripemd256;
24 
25 private import tango.util.digest.MerkleDamgard;
26 
27 public  import tango.util.digest.Digest;
28 
29 /*******************************************************************************
30 
31 *******************************************************************************/
32 
33 final class Ripemd256 : MerkleDamgard
34 {
35         private uint[8]        context;
36         private enum uint      padChar = 0x80;
37 
38         /***********************************************************************
39 
40         ***********************************************************************/
41 
42         private __gshared immutable uint[8] initial =
43         [
44   				0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476,
45   				0x76543210, 0xfedcba98, 0x89abcdef, 0x01234567
46         ];
47         
48         /***********************************************************************
49 
50         	Construct a Ripemd256
51 
52          ***********************************************************************/
53 
54         this() { }
55 
56         /***********************************************************************
57 
58         	The size of a Ripemd256 digest is 32 bytes
59         
60          ***********************************************************************/
61 
62         override uint digestSize() {return 32;}
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 Ripemd256 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 Ripemd256 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;
192         	uint ar, br, cr, dr;
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             ar = context[4];
203             br = context[5];
204             cr = context[6];
205             dr = context[7];
206 
207             // Round 1 and parallel round 1
208             al = rotateLeft(al + (bl ^ cl ^ dl) + x[0], 11);
209             ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[5] + 0x50a28be6, 8);
210             dl = rotateLeft(dl + (al ^ bl ^ cl) + x[1], 14);
211             dr = rotateLeft(dr + ((ar & cr) | (br & ~(cr))) + x[14] + 0x50a28be6, 9);
212             cl = rotateLeft(cl + (dl ^ al ^ bl) + x[2], 15);
213             cr = rotateLeft(cr + ((dr & br) | (ar & ~(br))) + x[7] + 0x50a28be6, 9);
214             bl = rotateLeft(bl + (cl ^ dl ^ al) + x[3], 12);
215             br = rotateLeft(br + ((cr & ar) | (dr & ~(ar))) + x[0] + 0x50a28be6, 11);
216             al = rotateLeft(al + (bl ^ cl ^ dl) + x[4], 5);
217             ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[9] + 0x50a28be6, 13);
218             dl = rotateLeft(dl + (al ^ bl ^ cl) + x[5], 8);
219             dr = rotateLeft(dr + ((ar & cr) | (br & ~(cr))) + x[2] + 0x50a28be6, 15);
220             cl = rotateLeft(cl + (dl ^ al ^ bl) + x[6], 7);
221             cr = rotateLeft(cr + ((dr & br) | (ar & ~(br))) + x[11] + 0x50a28be6, 15);
222             bl = rotateLeft(bl + (cl ^ dl ^ al) + x[7], 9);
223             br = rotateLeft(br + ((cr & ar) | (dr & ~(ar))) + x[4] + 0x50a28be6, 5);
224             al = rotateLeft(al + (bl ^ cl ^ dl) + x[8], 11);
225             ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[13] + 0x50a28be6, 7);
226             dl = rotateLeft(dl + (al ^ bl ^ cl) + x[9], 13);
227             dr = rotateLeft(dr + ((ar & cr) | (br & ~(cr))) + x[6] + 0x50a28be6, 7);
228             cl = rotateLeft(cl + (dl ^ al ^ bl) + x[10], 14);
229             cr = rotateLeft(cr + ((dr & br) | (ar & ~(br))) + x[15] + 0x50a28be6, 8);
230             bl = rotateLeft(bl + (cl ^ dl ^ al) + x[11], 15);
231             br = rotateLeft(br + ((cr & ar) | (dr & ~(ar))) + x[8] + 0x50a28be6, 11);
232             al = rotateLeft(al + (bl ^ cl ^ dl) + x[12], 6);
233             ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[1] + 0x50a28be6, 14);
234             dl = rotateLeft(dl + (al ^ bl ^ cl) + x[13], 7);
235             dr = rotateLeft(dr + ((ar & cr) | (br & ~(cr))) + x[10] + 0x50a28be6, 14);
236             cl = rotateLeft(cl + (dl ^ al ^ bl) + x[14], 9);
237             cr = rotateLeft(cr + ((dr & br) | (ar & ~(br))) + x[3] + 0x50a28be6, 12);
238             bl = rotateLeft(bl + (cl ^ dl ^ al) + x[15], 8);
239             br = rotateLeft(br + ((cr & ar) | (dr & ~(ar))) + x[12] + 0x50a28be6, 6);
240             
241             t = al; al = ar; ar = t;
242             
243             // Round 2 and parallel round 2
244             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[7] + 0x5a827999, 7);
245             ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[6] + 0x5c4dd124, 9);
246             dl = rotateLeft(dl + (((bl ^ cl) & al) ^ cl) + x[4] + 0x5a827999, 6);
247             dr = rotateLeft(dr + ((ar | ~(br)) ^ cr) + x[11] + 0x5c4dd124, 13);
248             cl = rotateLeft(cl + (((al ^ bl) & dl) ^ bl) + x[13] + 0x5a827999, 8);
249             cr = rotateLeft(cr + ((dr | ~(ar)) ^ br) + x[3] + 0x5c4dd124, 15);
250             bl = rotateLeft(bl + (((dl ^ al) & cl) ^ al) + x[1] + 0x5a827999, 13);
251             br = rotateLeft(br + ((cr | ~(dr)) ^ ar) + x[7] + 0x5c4dd124, 7);
252             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[10] + 0x5a827999, 11);
253             ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[0] + 0x5c4dd124, 12);
254             dl = rotateLeft(dl + (((bl ^ cl) & al) ^ cl) + x[6] + 0x5a827999, 9);
255             dr = rotateLeft(dr + ((ar | ~(br)) ^ cr) + x[13] + 0x5c4dd124, 8);
256             cl = rotateLeft(cl + (((al ^ bl) & dl) ^ bl) + x[15] + 0x5a827999, 7);
257             cr = rotateLeft(cr + ((dr | ~(ar)) ^ br) + x[5] + 0x5c4dd124, 9);
258             bl = rotateLeft(bl + (((dl ^ al) & cl) ^ al) + x[3] + 0x5a827999, 15);
259             br = rotateLeft(br + ((cr | ~(dr)) ^ ar) + x[10] + 0x5c4dd124, 11);
260             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[12] + 0x5a827999, 7);
261             ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[14] + 0x5c4dd124, 7);
262             dl = rotateLeft(dl + (((bl ^ cl) & al) ^ cl) + x[0] + 0x5a827999, 12);
263             dr = rotateLeft(dr + ((ar | ~(br)) ^ cr) + x[15] + 0x5c4dd124, 7);
264             cl = rotateLeft(cl + (((al ^ bl) & dl) ^ bl) + x[9] + 0x5a827999, 15);
265             cr = rotateLeft(cr + ((dr | ~(ar)) ^ br) + x[8] + 0x5c4dd124, 12);
266             bl = rotateLeft(bl + (((dl ^ al) & cl) ^ al) + x[5] + 0x5a827999, 9);
267             br = rotateLeft(br + ((cr | ~(dr)) ^ ar) + x[12] + 0x5c4dd124, 7);
268             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[2] + 0x5a827999, 11);
269             ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[4] + 0x5c4dd124, 6);
270             dl = rotateLeft(dl + (((bl ^ cl) & al) ^ cl) + x[14] + 0x5a827999, 7);
271             dr = rotateLeft(dr + ((ar | ~(br)) ^ cr) + x[9] + 0x5c4dd124, 15);
272             cl = rotateLeft(cl + (((al ^ bl) & dl) ^ bl) + x[11] + 0x5a827999, 13);
273             cr = rotateLeft(cr + ((dr | ~(ar)) ^ br) + x[1] + 0x5c4dd124, 13);
274             bl = rotateLeft(bl + (((dl ^ al) & cl) ^ al) + x[8] + 0x5a827999, 12);
275             br = rotateLeft(br + ((cr | ~(dr)) ^ ar) + x[2] + 0x5c4dd124, 11);
276             
277             t = bl; bl = br; br = t;
278             
279             // Round 3 and parallel round 3
280             al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[3] + 0x6ed9eba1, 11);
281             ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[15] + 0x6d703ef3, 9);
282             dl = rotateLeft(dl + ((al | ~(bl)) ^ cl) + x[10] + 0x6ed9eba1, 13);
283             dr = rotateLeft(dr + (((br ^ cr) & ar) ^ cr) + x[5] + 0x6d703ef3, 7);
284             cl = rotateLeft(cl + ((dl | ~(al)) ^ bl) + x[14] + 0x6ed9eba1, 6);
285             cr = rotateLeft(cr + (((ar ^ br) & dr) ^ br) + x[1] + 0x6d703ef3, 15);
286             bl = rotateLeft(bl + ((cl | ~(dl)) ^ al) + x[4] + 0x6ed9eba1, 7);
287             br = rotateLeft(br + (((dr ^ ar) & cr) ^ ar) + x[3] + 0x6d703ef3, 11);
288             al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[9] + 0x6ed9eba1, 14);
289             ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[7] + 0x6d703ef3, 8);
290             dl = rotateLeft(dl + ((al | ~(bl)) ^ cl) + x[15] + 0x6ed9eba1, 9);
291             dr = rotateLeft(dr + (((br ^ cr) & ar) ^ cr) + x[14] + 0x6d703ef3, 6);
292             cl = rotateLeft(cl + ((dl | ~(al)) ^ bl) + x[8] + 0x6ed9eba1, 13);
293             cr = rotateLeft(cr + (((ar ^ br) & dr) ^ br) + x[6] + 0x6d703ef3, 6);
294             bl = rotateLeft(bl + ((cl | ~(dl)) ^ al) + x[1] + 0x6ed9eba1, 15);
295             br = rotateLeft(br + (((dr ^ ar) & cr) ^ ar) + x[9] + 0x6d703ef3, 14);
296             al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[2] + 0x6ed9eba1, 14);
297             ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[11] + 0x6d703ef3, 12);
298             dl = rotateLeft(dl + ((al | ~(bl)) ^ cl) + x[7] + 0x6ed9eba1, 8);
299             dr = rotateLeft(dr + (((br ^ cr) & ar) ^ cr) + x[8] + 0x6d703ef3, 13);
300             cl = rotateLeft(cl + ((dl | ~(al)) ^ bl) + x[0] + 0x6ed9eba1, 13);
301             cr = rotateLeft(cr + (((ar ^ br) & dr) ^ br) + x[12] + 0x6d703ef3, 5);
302             bl = rotateLeft(bl + ((cl | ~(dl)) ^ al) + x[6] + 0x6ed9eba1, 6);
303             br = rotateLeft(br + (((dr ^ ar) & cr) ^ ar) + x[2] + 0x6d703ef3, 14);
304             al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[13] + 0x6ed9eba1, 5);
305             ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[10] + 0x6d703ef3, 13);
306             dl = rotateLeft(dl + ((al | ~(bl)) ^ cl) + x[11] + 0x6ed9eba1, 12);
307             dr = rotateLeft(dr + (((br ^ cr) & ar) ^ cr) + x[0] + 0x6d703ef3, 13);
308             cl = rotateLeft(cl + ((dl | ~(al)) ^ bl) + x[5] + 0x6ed9eba1, 7);
309             cr = rotateLeft(cr + (((ar ^ br) & dr) ^ br) + x[4] + 0x6d703ef3, 7);
310             bl = rotateLeft(bl + ((cl | ~(dl)) ^ al) + x[12] + 0x6ed9eba1, 5);
311             br = rotateLeft(br + (((dr ^ ar) & cr) ^ ar) + x[13] + 0x6d703ef3, 5);
312             
313             t = cl; cl = cr; cr = t;
314             
315             // Round 4 and parallel round 4
316             al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[1] + 0x8f1bbcdc, 11);
317             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[8], 15);
318             dl = rotateLeft(dl + ((al & cl) | (bl & ~(cl))) + x[9] + 0x8f1bbcdc, 12);
319             dr = rotateLeft(dr + (ar ^ br ^ cr) + x[6], 5);
320             cl = rotateLeft(cl + ((dl & bl) | (al & ~(bl))) + x[11] + 0x8f1bbcdc, 14);
321             cr = rotateLeft(cr + (dr ^ ar ^ br) + x[4], 8);
322             bl = rotateLeft(bl + ((cl & al) | (dl & ~(al))) + x[10] + 0x8f1bbcdc, 15);
323             br = rotateLeft(br + (cr ^ dr ^ ar) + x[1], 11);
324             al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[0] + 0x8f1bbcdc, 14);
325             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[3], 14);
326             dl = rotateLeft(dl + ((al & cl) | (bl & ~(cl))) + x[8] + 0x8f1bbcdc, 15);
327             dr = rotateLeft(dr + (ar ^ br ^ cr) + x[11], 14);
328             cl = rotateLeft(cl + ((dl & bl) | (al & ~(bl))) + x[12] + 0x8f1bbcdc, 9);
329             cr = rotateLeft(cr + (dr ^ ar ^ br) + x[15], 6);
330             bl = rotateLeft(bl + ((cl & al) | (dl & ~(al))) + x[4] + 0x8f1bbcdc, 8);
331             br = rotateLeft(br + (cr ^ dr ^ ar) + x[0], 14);
332             al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[13] + 0x8f1bbcdc, 9);
333             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[5], 6);
334             dl = rotateLeft(dl + ((al & cl) | (bl & ~(cl))) + x[3] + 0x8f1bbcdc, 14);
335             dr = rotateLeft(dr + (ar ^ br ^ cr) + x[12], 9);
336             cl = rotateLeft(cl + ((dl & bl) | (al & ~(bl))) + x[7] + 0x8f1bbcdc, 5);
337             cr = rotateLeft(cr + (dr ^ ar ^ br) + x[2], 12);
338             bl = rotateLeft(bl + ((cl & al) | (dl & ~(al))) + x[15] + 0x8f1bbcdc, 6);
339             br = rotateLeft(br + (cr ^ dr ^ ar) + x[13], 9);
340             al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[14] + 0x8f1bbcdc, 8);
341             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[9], 12);
342             dl = rotateLeft(dl + ((al & cl) | (bl & ~(cl))) + x[5] + 0x8f1bbcdc, 6);
343             dr = rotateLeft(dr + (ar ^ br ^ cr) + x[7], 5);
344             cl = rotateLeft(cl + ((dl & bl) | (al & ~(bl))) + x[6] + 0x8f1bbcdc, 5);
345             cr = rotateLeft(cr + (dr ^ ar ^ br) + x[10], 15);
346             bl = rotateLeft(bl + ((cl & al) | (dl & ~(al))) + x[2] + 0x8f1bbcdc, 12);
347             br = rotateLeft(br + (cr ^ dr ^ ar) + x[14], 8);
348             
349             // Do not swap dl and dr; simply add the right value to context 
350 
351             context[0] += al;
352             context[1] += bl;
353             context[2] += cl;
354             context[3] += dr;
355             context[4] += ar;
356             context[5] += br;
357             context[6] += cr;
358             context[7] += dl;
359 
360             x[] = 0;
361         }
362 
363 }
364 
365 /*******************************************************************************
366 
367 *******************************************************************************/
368 
369 debug(UnitTest)
370 {
371     unittest
372     {
373     __gshared immutable immutable(char)[][] strings =
374     [
375             "",
376             "a",
377             "abc",
378             "message digest",
379             "abcdefghijklmnopqrstuvwxyz",
380             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
381             "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
382             "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
383     ];
384 
385     __gshared immutable immutable(char)[][] results =
386     [
387             "02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d",
388             "f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925",
389             "afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65",
390             "87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e",
391             "649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133",
392             "3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f",
393             "5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8",
394             "06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd"
395     ];
396 
397     Ripemd256 h = new Ripemd256();
398 
399     foreach (int i, immutable(char)[] s; strings)
400             {
401             h.update(cast(ubyte[]) s);
402             char[] d = h.hexDigest();
403 
404             assert(d == results[i],":("~s~")("~d~")!=("~results[i]~")");
405             }
406 
407     char[] s = new char[1000000];
408     for (auto i = 0; i < s.length; i++) s[i] = 'a';
409     immutable(char)[] result = "ac953744e10e31514c150d4d8d7b677342e33399788296e43ae4850ce4f97978";
410     h.update(cast(ubyte[]) s);
411     char[] d = h.hexDigest();
412 
413     assert(d == result,":(1 million times \"a\")("~d~")!=("~result~")");
414     }
415 	
416 }