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