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 Ripemd128 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.Ripemd128;
24 
25 private import tango.util.digest.MerkleDamgard;
26 
27 public  import tango.util.digest.Digest;
28 
29 /*******************************************************************************
30 
31 *******************************************************************************/
32 
33 final class Ripemd128 : MerkleDamgard
34 {
35         private uint[4]        context;
36         private enum uint      padChar = 0x80;
37 
38         /***********************************************************************
39 
40         ***********************************************************************/
41 
42         private __gshared immutable uint[4] initial =
43         [
44   				0x67452301,
45   				0xefcdab89,
46   				0x98badcfe,
47   				0x10325476
48         ];
49         
50         /***********************************************************************
51 
52         	Construct a Ripemd128
53 
54          ***********************************************************************/
55 
56         this() { }
57 
58         /***********************************************************************
59 
60         	The size of a Ripemd128 digest is 16 bytes
61         
62          ***********************************************************************/
63 
64         override uint digestSize() {return 16;}
65 
66 
67         /***********************************************************************
68 
69         	Initialize the cipher
70 
71         	Remarks:
72         		Returns the cipher state to it's initial value
73 
74          ***********************************************************************/
75 
76         override void reset()
77         {
78         	super.reset();
79         	context[] = initial[];
80         }
81 
82         /***********************************************************************
83 
84         	Obtain the digest
85 
86         	Returns:
87         		the digest
88 
89         	Remarks:
90         		Returns a digest of the current cipher state, this may be the
91         		final digest, or a digest of the state between calls to update()
92 
93          ***********************************************************************/
94 
95         override void createDigest(ubyte[] buf)
96         {
97             version (BigEndian)
98             	ByteSwap.swap32 (context.ptr, context.length * uint.sizeof);
99 
100         	buf[] = (cast(ubyte[]) context)[];
101         }
102 
103 
104         /***********************************************************************
105 
106          	block size
107 
108         	Returns:
109         	the block size
110 
111         	Remarks:
112         	Specifies the size (in bytes) of the block of data to pass to
113         	each call to transform(). For Ripemd128 the blockSize is 64.
114 
115          ***********************************************************************/
116 
117         protected override uint blockSize() { return 64; }
118 
119         /***********************************************************************
120 
121         	Length padding size
122 
123         	Returns:
124         	the length padding size
125 
126         	Remarks:
127         	Specifies the size (in bytes) of the padding which uses the
128         	length of the data which has been ciphered, this padding is
129         	carried out by the padLength method. For Ripemd128 the addSize is 8.
130 
131          ***********************************************************************/
132 
133         protected override uint addSize()   { return 8;  }
134 
135         /***********************************************************************
136 
137         	Pads the cipher data
138 
139         	Params:
140         	data = a slice of the cipher buffer to fill with padding
141 
142         	Remarks:
143         	Fills the passed buffer slice with the appropriate padding for
144         	the final call to transform(). This padding will fill the cipher
145         	buffer up to blockSize()-addSize().
146 
147          ***********************************************************************/
148 
149         protected override void padMessage(ubyte[] at)
150         {
151         	at[0] = padChar;
152         	at[1..at.length] = 0;
153         }
154 
155         /***********************************************************************
156 
157         	Performs the length padding
158 
159         	Params:
160         	data   = the slice of the cipher buffer to fill with padding
161         	length = the length of the data which has been ciphered
162 
163         	Remarks:
164         	Fills the passed buffer slice with addSize() bytes of padding
165         	based on the length in bytes of the input data which has been
166         	ciphered.
167 
168          ***********************************************************************/
169 
170         protected override void padLength(ubyte[] at, ulong length)
171         {
172         	length <<= 3;
173         	littleEndian64((cast(ubyte*)&length)[0..8],cast(ulong[]) at); 
174         }
175 
176         /***********************************************************************
177 
178         	Performs the cipher on a block of data
179 
180         	Params:
181         	data = the block of data to cipher
182 
183         	Remarks:
184         	The actual cipher algorithm is carried out by this method on
185         	the passed block of data. This method is called for every
186         	blockSize() bytes of input data and once more with the remaining
187         	data padded to blockSize().
188 
189          ***********************************************************************/
190 
191         protected override void transform(const(ubyte[]) input)
192         {
193         	uint al, bl, cl, dl;
194         	uint ar, br, cr, dr;
195             uint[16] x;
196             
197             littleEndian32(input,x);
198 
199             al = ar = context[0];
200             bl = br = context[1];
201             cl = cr = context[2];
202             dl = dr = context[3];
203 
204             // Round 1 and parallel round 1
205             al = rotateLeft(al + (bl ^ cl ^ dl) + x[0], 11);
206             ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[5] + 0x50a28be6, 8);
207             dl = rotateLeft(dl + (al ^ bl ^ cl) + x[1], 14);
208             dr = rotateLeft(dr + ((ar & cr) | (br & ~(cr))) + x[14] + 0x50a28be6, 9);
209             cl = rotateLeft(cl + (dl ^ al ^ bl) + x[2], 15);
210             cr = rotateLeft(cr + ((dr & br) | (ar & ~(br))) + x[7] + 0x50a28be6, 9);
211             bl = rotateLeft(bl + (cl ^ dl ^ al) + x[3], 12);
212             br = rotateLeft(br + ((cr & ar) | (dr & ~(ar))) + x[0] + 0x50a28be6, 11);
213             al = rotateLeft(al + (bl ^ cl ^ dl) + x[4], 5);
214             ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[9] + 0x50a28be6, 13);
215             dl = rotateLeft(dl + (al ^ bl ^ cl) + x[5], 8);
216             dr = rotateLeft(dr + ((ar & cr) | (br & ~(cr))) + x[2] + 0x50a28be6, 15);
217             cl = rotateLeft(cl + (dl ^ al ^ bl) + x[6], 7);
218             cr = rotateLeft(cr + ((dr & br) | (ar & ~(br))) + x[11] + 0x50a28be6, 15);
219             bl = rotateLeft(bl + (cl ^ dl ^ al) + x[7], 9);
220             br = rotateLeft(br + ((cr & ar) | (dr & ~(ar))) + x[4] + 0x50a28be6, 5);
221             al = rotateLeft(al + (bl ^ cl ^ dl) + x[8], 11);
222             ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[13] + 0x50a28be6, 7);
223             dl = rotateLeft(dl + (al ^ bl ^ cl) + x[9], 13);
224             dr = rotateLeft(dr + ((ar & cr) | (br & ~(cr))) + x[6] + 0x50a28be6, 7);
225             cl = rotateLeft(cl + (dl ^ al ^ bl) + x[10], 14);
226             cr = rotateLeft(cr + ((dr & br) | (ar & ~(br))) + x[15] + 0x50a28be6, 8);
227             bl = rotateLeft(bl + (cl ^ dl ^ al) + x[11], 15);
228             br = rotateLeft(br + ((cr & ar) | (dr & ~(ar))) + x[8] + 0x50a28be6, 11);
229             al = rotateLeft(al + (bl ^ cl ^ dl) + x[12], 6);
230             ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[1] + 0x50a28be6, 14);
231             dl = rotateLeft(dl + (al ^ bl ^ cl) + x[13], 7);
232             dr = rotateLeft(dr + ((ar & cr) | (br & ~(cr))) + x[10] + 0x50a28be6, 14);
233             cl = rotateLeft(cl + (dl ^ al ^ bl) + x[14], 9);
234             cr = rotateLeft(cr + ((dr & br) | (ar & ~(br))) + x[3] + 0x50a28be6, 12);
235             bl = rotateLeft(bl + (cl ^ dl ^ al) + x[15], 8);
236             br = rotateLeft(br + ((cr & ar) | (dr & ~(ar))) + x[12] + 0x50a28be6, 6);
237             
238             // Round 2 and parallel round 2
239             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[7] + 0x5a827999, 7);
240             ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[6] + 0x5c4dd124, 9);
241             dl = rotateLeft(dl + (((bl ^ cl) & al) ^ cl) + x[4] + 0x5a827999, 6);
242             dr = rotateLeft(dr + ((ar | ~(br)) ^ cr) + x[11] + 0x5c4dd124, 13);
243             cl = rotateLeft(cl + (((al ^ bl) & dl) ^ bl) + x[13] + 0x5a827999, 8);
244             cr = rotateLeft(cr + ((dr | ~(ar)) ^ br) + x[3] + 0x5c4dd124, 15);
245             bl = rotateLeft(bl + (((dl ^ al) & cl) ^ al) + x[1] + 0x5a827999, 13);
246             br = rotateLeft(br + ((cr | ~(dr)) ^ ar) + x[7] + 0x5c4dd124, 7);
247             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[10] + 0x5a827999, 11);
248             ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[0] + 0x5c4dd124, 12);
249             dl = rotateLeft(dl + (((bl ^ cl) & al) ^ cl) + x[6] + 0x5a827999, 9);
250             dr = rotateLeft(dr + ((ar | ~(br)) ^ cr) + x[13] + 0x5c4dd124, 8);
251             cl = rotateLeft(cl + (((al ^ bl) & dl) ^ bl) + x[15] + 0x5a827999, 7);
252             cr = rotateLeft(cr + ((dr | ~(ar)) ^ br) + x[5] + 0x5c4dd124, 9);
253             bl = rotateLeft(bl + (((dl ^ al) & cl) ^ al) + x[3] + 0x5a827999, 15);
254             br = rotateLeft(br + ((cr | ~(dr)) ^ ar) + x[10] + 0x5c4dd124, 11);
255             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[12] + 0x5a827999, 7);
256             ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[14] + 0x5c4dd124, 7);
257             dl = rotateLeft(dl + (((bl ^ cl) & al) ^ cl) + x[0] + 0x5a827999, 12);
258             dr = rotateLeft(dr + ((ar | ~(br)) ^ cr) + x[15] + 0x5c4dd124, 7);
259             cl = rotateLeft(cl + (((al ^ bl) & dl) ^ bl) + x[9] + 0x5a827999, 15);
260             cr = rotateLeft(cr + ((dr | ~(ar)) ^ br) + x[8] + 0x5c4dd124, 12);
261             bl = rotateLeft(bl + (((dl ^ al) & cl) ^ al) + x[5] + 0x5a827999, 9);
262             br = rotateLeft(br + ((cr | ~(dr)) ^ ar) + x[12] + 0x5c4dd124, 7);
263             al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[2] + 0x5a827999, 11);
264             ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[4] + 0x5c4dd124, 6);
265             dl = rotateLeft(dl + (((bl ^ cl) & al) ^ cl) + x[14] + 0x5a827999, 7);
266             dr = rotateLeft(dr + ((ar | ~(br)) ^ cr) + x[9] + 0x5c4dd124, 15);
267             cl = rotateLeft(cl + (((al ^ bl) & dl) ^ bl) + x[11] + 0x5a827999, 13);
268             cr = rotateLeft(cr + ((dr | ~(ar)) ^ br) + x[1] + 0x5c4dd124, 13);
269             bl = rotateLeft(bl + (((dl ^ al) & cl) ^ al) + x[8] + 0x5a827999, 12);
270             br = rotateLeft(br + ((cr | ~(dr)) ^ ar) + x[2] + 0x5c4dd124, 11);
271             
272             // Round 3 and parallel round 3
273             al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[3] + 0x6ed9eba1, 11);
274             ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[15] + 0x6d703ef3, 9);
275             dl = rotateLeft(dl + ((al | ~(bl)) ^ cl) + x[10] + 0x6ed9eba1, 13);
276             dr = rotateLeft(dr + (((br ^ cr) & ar) ^ cr) + x[5] + 0x6d703ef3, 7);
277             cl = rotateLeft(cl + ((dl | ~(al)) ^ bl) + x[14] + 0x6ed9eba1, 6);
278             cr = rotateLeft(cr + (((ar ^ br) & dr) ^ br) + x[1] + 0x6d703ef3, 15);
279             bl = rotateLeft(bl + ((cl | ~(dl)) ^ al) + x[4] + 0x6ed9eba1, 7);
280             br = rotateLeft(br + (((dr ^ ar) & cr) ^ ar) + x[3] + 0x6d703ef3, 11);
281             al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[9] + 0x6ed9eba1, 14);
282             ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[7] + 0x6d703ef3, 8);
283             dl = rotateLeft(dl + ((al | ~(bl)) ^ cl) + x[15] + 0x6ed9eba1, 9);
284             dr = rotateLeft(dr + (((br ^ cr) & ar) ^ cr) + x[14] + 0x6d703ef3, 6);
285             cl = rotateLeft(cl + ((dl | ~(al)) ^ bl) + x[8] + 0x6ed9eba1, 13);
286             cr = rotateLeft(cr + (((ar ^ br) & dr) ^ br) + x[6] + 0x6d703ef3, 6);
287             bl = rotateLeft(bl + ((cl | ~(dl)) ^ al) + x[1] + 0x6ed9eba1, 15);
288             br = rotateLeft(br + (((dr ^ ar) & cr) ^ ar) + x[9] + 0x6d703ef3, 14);
289             al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[2] + 0x6ed9eba1, 14);
290             ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[11] + 0x6d703ef3, 12);
291             dl = rotateLeft(dl + ((al | ~(bl)) ^ cl) + x[7] + 0x6ed9eba1, 8);
292             dr = rotateLeft(dr + (((br ^ cr) & ar) ^ cr) + x[8] + 0x6d703ef3, 13);
293             cl = rotateLeft(cl + ((dl | ~(al)) ^ bl) + x[0] + 0x6ed9eba1, 13);
294             cr = rotateLeft(cr + (((ar ^ br) & dr) ^ br) + x[12] + 0x6d703ef3, 5);
295             bl = rotateLeft(bl + ((cl | ~(dl)) ^ al) + x[6] + 0x6ed9eba1, 6);
296             br = rotateLeft(br + (((dr ^ ar) & cr) ^ ar) + x[2] + 0x6d703ef3, 14);
297             al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[13] + 0x6ed9eba1, 5);
298             ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[10] + 0x6d703ef3, 13);
299             dl = rotateLeft(dl + ((al | ~(bl)) ^ cl) + x[11] + 0x6ed9eba1, 12);
300             dr = rotateLeft(dr + (((br ^ cr) & ar) ^ cr) + x[0] + 0x6d703ef3, 13);
301             cl = rotateLeft(cl + ((dl | ~(al)) ^ bl) + x[5] + 0x6ed9eba1, 7);
302             cr = rotateLeft(cr + (((ar ^ br) & dr) ^ br) + x[4] + 0x6d703ef3, 7);
303             bl = rotateLeft(bl + ((cl | ~(dl)) ^ al) + x[12] + 0x6ed9eba1, 5);
304             br = rotateLeft(br + (((dr ^ ar) & cr) ^ ar) + x[13] + 0x6d703ef3, 5);
305             
306             // Round 4 and parallel round 4
307             al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[1] + 0x8f1bbcdc, 11);
308             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[8], 15);
309             dl = rotateLeft(dl + ((al & cl) | (bl & ~(cl))) + x[9] + 0x8f1bbcdc, 12);
310             dr = rotateLeft(dr + (ar ^ br ^ cr) + x[6], 5);
311             cl = rotateLeft(cl + ((dl & bl) | (al & ~(bl))) + x[11] + 0x8f1bbcdc, 14);
312             cr = rotateLeft(cr + (dr ^ ar ^ br) + x[4], 8);
313             bl = rotateLeft(bl + ((cl & al) | (dl & ~(al))) + x[10] + 0x8f1bbcdc, 15);
314             br = rotateLeft(br + (cr ^ dr ^ ar) + x[1], 11);
315             al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[0] + 0x8f1bbcdc, 14);
316             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[3], 14);
317             dl = rotateLeft(dl + ((al & cl) | (bl & ~(cl))) + x[8] + 0x8f1bbcdc, 15);
318             dr = rotateLeft(dr + (ar ^ br ^ cr) + x[11], 14);
319             cl = rotateLeft(cl + ((dl & bl) | (al & ~(bl))) + x[12] + 0x8f1bbcdc, 9);
320             cr = rotateLeft(cr + (dr ^ ar ^ br) + x[15], 6);
321             bl = rotateLeft(bl + ((cl & al) | (dl & ~(al))) + x[4] + 0x8f1bbcdc, 8);
322             br = rotateLeft(br + (cr ^ dr ^ ar) + x[0], 14);
323             al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[13] + 0x8f1bbcdc, 9);
324             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[5], 6);
325             dl = rotateLeft(dl + ((al & cl) | (bl & ~(cl))) + x[3] + 0x8f1bbcdc, 14);
326             dr = rotateLeft(dr + (ar ^ br ^ cr) + x[12], 9);
327             cl = rotateLeft(cl + ((dl & bl) | (al & ~(bl))) + x[7] + 0x8f1bbcdc, 5);
328             cr = rotateLeft(cr + (dr ^ ar ^ br) + x[2], 12);
329             bl = rotateLeft(bl + ((cl & al) | (dl & ~(al))) + x[15] + 0x8f1bbcdc, 6);
330             br = rotateLeft(br + (cr ^ dr ^ ar) + x[13], 9);
331             al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[14] + 0x8f1bbcdc, 8);
332             ar = rotateLeft(ar + (br ^ cr ^ dr) + x[9], 12);
333             dl = rotateLeft(dl + ((al & cl) | (bl & ~(cl))) + x[5] + 0x8f1bbcdc, 6);
334             dr = rotateLeft(dr + (ar ^ br ^ cr) + x[7], 5);
335             cl = rotateLeft(cl + ((dl & bl) | (al & ~(bl))) + x[6] + 0x8f1bbcdc, 5);
336             cr = rotateLeft(cr + (dr ^ ar ^ br) + x[10], 15);
337             bl = rotateLeft(bl + ((cl & al) | (dl & ~(al))) + x[2] + 0x8f1bbcdc, 12);
338             br = rotateLeft(br + (cr ^ dr ^ ar) + x[14], 8);
339             
340             uint t = context[1] + cl + dr;
341             context[1] = context[2] + dl + ar;
342             context[2] = context[3] + al + br;
343             context[3] = context[0] + bl + cr;
344             context[0] = t;
345 
346             x[] = 0;
347         }
348 
349 }
350 
351 /*******************************************************************************
352 
353 *******************************************************************************/
354 
355 debug(UnitTest)
356 {
357     unittest
358     {
359     __gshared immutable immutable(char)[][] strings =
360     [
361             "",
362             "a",
363             "abc",
364             "message digest",
365             "abcdefghijklmnopqrstuvwxyz",
366             "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
367             "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
368             "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
369     ];
370 
371     __gshared immutable immutable(char)[][] results =
372     [
373             "cdf26213a150dc3ecb610f18f6b38b46",
374             "86be7afa339d0fc7cfc785e72f578d33",
375             "c14a12199c66e4ba84636b0f69144c77",
376             "9e327b3d6e523062afc1132d7df9d1b8",
377             "fd2aa607f71dc8f510714922b371834e",
378             "a1aa0689d0fafa2ddc22e88b49133a06",
379             "d1e959eb179c911faea4624c60c5c702",
380             "3f45ef194732c2dbb2c4a2c769795fa3"
381     ];
382 
383     Ripemd128 h = new Ripemd128();
384 
385     foreach (int i, immutable(char)[] s; strings)
386             {
387             h.update(cast(ubyte[]) s);
388             char[] d = h.hexDigest();
389 
390             assert(d == results[i],":("~s~")("~d~")!=("~results[i]~")");
391             }
392 
393     char[] s = new char[1000000];
394     for (auto i = 0; i < s.length; i++) s[i] = 'a';
395     immutable(char)[] result = "4a7f5723f954eba1216c9d8f6320431f";
396     h.update(cast(ubyte[]) s);
397     char[] d = h.hexDigest();
398 
399     assert(d == result,":(1 million times \"a\")("~d~")!=("~result~")");
400     }
401 	
402 }