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