]> git.ipfire.org Git - thirdparty/gcc.git/blame - libphobos/src/std/digest/ripemd.d
d: Import dmd b8384668f, druntime e6caaab9, phobos 5ab9ad256 (v2.098.0-beta.1)
[thirdparty/gcc.git] / libphobos / src / std / digest / ripemd.d
CommitLineData
b4c522fa
IB
1/**
2 * Computes RIPEMD-160 hashes of arbitrary data. RIPEMD-160 hashes are 20 byte quantities
3 * that are like a checksum or CRC, but are more robust.
4 *
5$(SCRIPT inhibitQuickIndex = 1;)
6
7$(DIVC quickindex,
8$(BOOKTABLE ,
9$(TR $(TH Category) $(TH Functions)
10)
11$(TR $(TDNW Template API) $(TD $(MYREF RIPEMD160)
12)
13)
14$(TR $(TDNW OOP API) $(TD $(MYREF RIPEMD160Digest))
15)
16$(TR $(TDNW Helpers) $(TD $(MYREF ripemd160Of))
17)
18)
19)
20
21 * This module conforms to the APIs defined in $(MREF std, digest). To understand the
22 * differences between the template and the OOP API, see $(MREF std, digest).
23 *
5fee5ec3 24 * This module publicly imports `std.digest` and can be used as a stand-alone
b4c522fa
IB
25 * module.
26 *
27 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
28 *
29 * CTFE:
30 * Digests do not work in CTFE
31 *
32 * Authors:
33 * Kai Nacke $(BR)
34 * The algorithm was designed by Hans Dobbertin, Antoon Bosselaers, and Bart Preneel. $(BR)
35 * The D implementation is a direct translation of the ANSI C implementation by Antoon Bosselaers.
36 *
37 * References:
38 * $(UL
39 * $(LI $(LINK2 http://homes.esat.kuleuven.be/~bosselae/ripemd160.html, The hash function RIPEMD-160))
40 * $(LI $(LINK2 http://en.wikipedia.org/wiki/RIPEMD-160, Wikipedia on RIPEMD-160))
41 * )
42 *
5fee5ec3 43 * Source: $(PHOBOSSRC std/digest/ripemd.d)
b4c522fa
IB
44 *
45 */
46
47module std.digest.ripemd;
48
49public import std.digest;
50
51///
52@safe unittest
53{
54 //Template API
55 import std.digest.md;
56
57 ubyte[20] hash = ripemd160Of("abc");
58 assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC");
59
60 //Feeding data
61 ubyte[1024] data;
62 RIPEMD160 md;
63 md.start();
64 md.put(data[]);
65 md.start(); //Start again
66 md.put(data[]);
67 hash = md.finish();
68}
69
70///
71@safe unittest
72{
73 //OOP API
74 import std.digest.md;
75
76 auto md = new RIPEMD160Digest();
77 ubyte[] hash = md.digest("abc");
78 assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC");
79
80 //Feeding data
81 ubyte[1024] data;
82 md.put(data[]);
83 md.reset(); //Start again
84 md.put(data[]);
85 hash = md.finish();
86}
87
b4c522fa
IB
88/**
89 * Template API RIPEMD160 implementation.
5fee5ec3 90 * See `std.digest` for differences between template and OOP API.
b4c522fa
IB
91 */
92struct RIPEMD160
93{
5fee5ec3 94 import core.bitop : rol;
b4c522fa
IB
95 private:
96 // magic initialization constants
97 uint[5] _state = [0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0]; // state (ABCDE)
98 ulong _count; //number of bits, modulo 2^64
99 ubyte[64] _buffer; // input buffer
100
101 static immutable ubyte[64] _padding =
102 [
103 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
106 ];
107
108 // F, G, H, I and J are basic RIPEMD160 functions
109 static @safe pure nothrow @nogc
110 {
111 uint F(uint x, uint y, uint z) { return x ^ y ^ z; }
112 uint G(uint x, uint y, uint z) { return (x & y) | (~x & z); }
113 uint H(uint x, uint y, uint z) { return (x | ~y) ^ z; }
114 uint I(uint x, uint y, uint z) { return (x & z) | (y & ~z); }
115 uint J(uint x, uint y, uint z) { return x ^ (y | ~z); }
116 }
117
118 /*
119 * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
120 * Rotation is separate from addition to prevent recomputation.
121 */
122
123 /* the ten basic operations FF() through III() */
124 static void FF(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s)
125 @safe pure nothrow @nogc
126 {
127 a += F(b, c, d) + x;
5fee5ec3
IB
128 a = rol(a, s) + e;
129 c = rol(c, 10);
b4c522fa
IB
130 }
131
132 static void GG(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s)
133 @safe pure nothrow @nogc
134 {
135 a += G(b, c, d) + x + 0x5a827999UL;
5fee5ec3
IB
136 a = rol(a, s) + e;
137 c = rol(c, 10);
b4c522fa
IB
138 }
139
140 static void HH(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s)
141 @safe pure nothrow @nogc
142 {
143 a += H(b, c, d) + x + 0x6ed9eba1UL;
5fee5ec3
IB
144 a = rol(a, s) + e;
145 c = rol(c, 10);
b4c522fa
IB
146 }
147
148 static void II(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s)
149 @safe pure nothrow @nogc
150 {
151 a += I(b, c, d) + x + 0x8f1bbcdcUL;
5fee5ec3
IB
152 a = rol(a, s) + e;
153 c = rol(c, 10);
b4c522fa
IB
154 }
155
156 static void JJ(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s)
157 @safe pure nothrow @nogc
158 {
159 a += J(b, c, d) + x + 0xa953fd4eUL;
5fee5ec3
IB
160 a = rol(a, s) + e;
161 c = rol(c, 10);
b4c522fa
IB
162 }
163
164 /*
165 * FFF, GGG, HHH, and III transformations for parallel rounds 1, 2, 3, and 4.
166 * Rotation is separate from addition to prevent recomputation.
167 */
168
169 static void FFF(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s)
170 @safe pure nothrow @nogc
171 {
172 a += F(b, c, d) + x;
5fee5ec3
IB
173 a = rol(a, s) + e;
174 c = rol(c, 10);
b4c522fa
IB
175 }
176
177 static void GGG(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s)
178 @safe pure nothrow @nogc
179 {
180 a += G(b, c, d) + x + 0x7a6d76e9UL;
5fee5ec3
IB
181 a = rol(a, s) + e;
182 c = rol(c, 10);
b4c522fa
IB
183 }
184
185 static void HHH(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s)
186 @safe pure nothrow @nogc
187 {
188 a += H(b, c, d) + x + 0x6d703ef3UL;
5fee5ec3
IB
189 a = rol(a, s) + e;
190 c = rol(c, 10);
b4c522fa
IB
191 }
192
193 static void III(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s)
194 @safe pure nothrow @nogc
195 {
196 a += I(b, c, d) + x + 0x5c4dd124UL;
5fee5ec3
IB
197 a = rol(a, s) + e;
198 c = rol(c, 10);
b4c522fa
IB
199 }
200
201 static void JJJ(ref uint a, uint b, ref uint c, uint d, uint e, uint x, uint s)
202 @safe pure nothrow @nogc
203 {
204 a += J(b, c, d) + x + 0x50a28be6UL;
5fee5ec3
IB
205 a = rol(a, s) + e;
206 c = rol(c, 10);
b4c522fa
IB
207 }
208
209 /*
210 * RIPEMD160 basic transformation. Transforms state based on block.
211 */
212
213 private void transform(const(ubyte[64])* block)
214 pure nothrow @nogc
215 {
216 uint aa = _state[0],
217 bb = _state[1],
218 cc = _state[2],
219 dd = _state[3],
220 ee = _state[4];
221 uint aaa = _state[0],
222 bbb = _state[1],
223 ccc = _state[2],
224 ddd = _state[3],
225 eee = _state[4];
226
227 uint[16] x = void;
228
229 version (BigEndian)
230 {
231 import std.bitmanip : littleEndianToNative;
232
233 for (size_t i = 0; i < 16; i++)
234 {
235 x[i] = littleEndianToNative!uint(*cast(ubyte[4]*)&(*block)[i*4]);
236 }
237 }
238 else
239 {
240 (cast(ubyte*) x.ptr)[0 .. 64] = (cast(ubyte*) block)[0 .. 64];
241 }
242
243 /* round 1 */
244 FF(aa, bb, cc, dd, ee, x[ 0], 11);
245 FF(ee, aa, bb, cc, dd, x[ 1], 14);
246 FF(dd, ee, aa, bb, cc, x[ 2], 15);
247 FF(cc, dd, ee, aa, bb, x[ 3], 12);
248 FF(bb, cc, dd, ee, aa, x[ 4], 5);
249 FF(aa, bb, cc, dd, ee, x[ 5], 8);
250 FF(ee, aa, bb, cc, dd, x[ 6], 7);
251 FF(dd, ee, aa, bb, cc, x[ 7], 9);
252 FF(cc, dd, ee, aa, bb, x[ 8], 11);
253 FF(bb, cc, dd, ee, aa, x[ 9], 13);
254 FF(aa, bb, cc, dd, ee, x[10], 14);
255 FF(ee, aa, bb, cc, dd, x[11], 15);
256 FF(dd, ee, aa, bb, cc, x[12], 6);
257 FF(cc, dd, ee, aa, bb, x[13], 7);
258 FF(bb, cc, dd, ee, aa, x[14], 9);
259 FF(aa, bb, cc, dd, ee, x[15], 8);
260
261 /* round 2 */
262 GG(ee, aa, bb, cc, dd, x[ 7], 7);
263 GG(dd, ee, aa, bb, cc, x[ 4], 6);
264 GG(cc, dd, ee, aa, bb, x[13], 8);
265 GG(bb, cc, dd, ee, aa, x[ 1], 13);
266 GG(aa, bb, cc, dd, ee, x[10], 11);
267 GG(ee, aa, bb, cc, dd, x[ 6], 9);
268 GG(dd, ee, aa, bb, cc, x[15], 7);
269 GG(cc, dd, ee, aa, bb, x[ 3], 15);
270 GG(bb, cc, dd, ee, aa, x[12], 7);
271 GG(aa, bb, cc, dd, ee, x[ 0], 12);
272 GG(ee, aa, bb, cc, dd, x[ 9], 15);
273 GG(dd, ee, aa, bb, cc, x[ 5], 9);
274 GG(cc, dd, ee, aa, bb, x[ 2], 11);
275 GG(bb, cc, dd, ee, aa, x[14], 7);
276 GG(aa, bb, cc, dd, ee, x[11], 13);
277 GG(ee, aa, bb, cc, dd, x[ 8], 12);
278
279 /* round 3 */
280 HH(dd, ee, aa, bb, cc, x[ 3], 11);
281 HH(cc, dd, ee, aa, bb, x[10], 13);
282 HH(bb, cc, dd, ee, aa, x[14], 6);
283 HH(aa, bb, cc, dd, ee, x[ 4], 7);
284 HH(ee, aa, bb, cc, dd, x[ 9], 14);
285 HH(dd, ee, aa, bb, cc, x[15], 9);
286 HH(cc, dd, ee, aa, bb, x[ 8], 13);
287 HH(bb, cc, dd, ee, aa, x[ 1], 15);
288 HH(aa, bb, cc, dd, ee, x[ 2], 14);
289 HH(ee, aa, bb, cc, dd, x[ 7], 8);
290 HH(dd, ee, aa, bb, cc, x[ 0], 13);
291 HH(cc, dd, ee, aa, bb, x[ 6], 6);
292 HH(bb, cc, dd, ee, aa, x[13], 5);
293 HH(aa, bb, cc, dd, ee, x[11], 12);
294 HH(ee, aa, bb, cc, dd, x[ 5], 7);
295 HH(dd, ee, aa, bb, cc, x[12], 5);
296
297 /* round 4 */
298 II(cc, dd, ee, aa, bb, x[ 1], 11);
299 II(bb, cc, dd, ee, aa, x[ 9], 12);
300 II(aa, bb, cc, dd, ee, x[11], 14);
301 II(ee, aa, bb, cc, dd, x[10], 15);
302 II(dd, ee, aa, bb, cc, x[ 0], 14);
303 II(cc, dd, ee, aa, bb, x[ 8], 15);
304 II(bb, cc, dd, ee, aa, x[12], 9);
305 II(aa, bb, cc, dd, ee, x[ 4], 8);
306 II(ee, aa, bb, cc, dd, x[13], 9);
307 II(dd, ee, aa, bb, cc, x[ 3], 14);
308 II(cc, dd, ee, aa, bb, x[ 7], 5);
309 II(bb, cc, dd, ee, aa, x[15], 6);
310 II(aa, bb, cc, dd, ee, x[14], 8);
311 II(ee, aa, bb, cc, dd, x[ 5], 6);
312 II(dd, ee, aa, bb, cc, x[ 6], 5);
313 II(cc, dd, ee, aa, bb, x[ 2], 12);
314
315 /* round 5 */
316 JJ(bb, cc, dd, ee, aa, x[ 4], 9);
317 JJ(aa, bb, cc, dd, ee, x[ 0], 15);
318 JJ(ee, aa, bb, cc, dd, x[ 5], 5);
319 JJ(dd, ee, aa, bb, cc, x[ 9], 11);
320 JJ(cc, dd, ee, aa, bb, x[ 7], 6);
321 JJ(bb, cc, dd, ee, aa, x[12], 8);
322 JJ(aa, bb, cc, dd, ee, x[ 2], 13);
323 JJ(ee, aa, bb, cc, dd, x[10], 12);
324 JJ(dd, ee, aa, bb, cc, x[14], 5);
325 JJ(cc, dd, ee, aa, bb, x[ 1], 12);
326 JJ(bb, cc, dd, ee, aa, x[ 3], 13);
327 JJ(aa, bb, cc, dd, ee, x[ 8], 14);
328 JJ(ee, aa, bb, cc, dd, x[11], 11);
329 JJ(dd, ee, aa, bb, cc, x[ 6], 8);
330 JJ(cc, dd, ee, aa, bb, x[15], 5);
331 JJ(bb, cc, dd, ee, aa, x[13], 6);
332
333 /* parallel round 1 */
334 JJJ(aaa, bbb, ccc, ddd, eee, x[ 5], 8);
335 JJJ(eee, aaa, bbb, ccc, ddd, x[14], 9);
336 JJJ(ddd, eee, aaa, bbb, ccc, x[ 7], 9);
337 JJJ(ccc, ddd, eee, aaa, bbb, x[ 0], 11);
338 JJJ(bbb, ccc, ddd, eee, aaa, x[ 9], 13);
339 JJJ(aaa, bbb, ccc, ddd, eee, x[ 2], 15);
340 JJJ(eee, aaa, bbb, ccc, ddd, x[11], 15);
341 JJJ(ddd, eee, aaa, bbb, ccc, x[ 4], 5);
342 JJJ(ccc, ddd, eee, aaa, bbb, x[13], 7);
343 JJJ(bbb, ccc, ddd, eee, aaa, x[ 6], 7);
344 JJJ(aaa, bbb, ccc, ddd, eee, x[15], 8);
345 JJJ(eee, aaa, bbb, ccc, ddd, x[ 8], 11);
346 JJJ(ddd, eee, aaa, bbb, ccc, x[ 1], 14);
347 JJJ(ccc, ddd, eee, aaa, bbb, x[10], 14);
348 JJJ(bbb, ccc, ddd, eee, aaa, x[ 3], 12);
349 JJJ(aaa, bbb, ccc, ddd, eee, x[12], 6);
350
351 /* parallel round 2 */
352 III(eee, aaa, bbb, ccc, ddd, x[ 6], 9);
353 III(ddd, eee, aaa, bbb, ccc, x[11], 13);
354 III(ccc, ddd, eee, aaa, bbb, x[ 3], 15);
355 III(bbb, ccc, ddd, eee, aaa, x[ 7], 7);
356 III(aaa, bbb, ccc, ddd, eee, x[ 0], 12);
357 III(eee, aaa, bbb, ccc, ddd, x[13], 8);
358 III(ddd, eee, aaa, bbb, ccc, x[ 5], 9);
359 III(ccc, ddd, eee, aaa, bbb, x[10], 11);
360 III(bbb, ccc, ddd, eee, aaa, x[14], 7);
361 III(aaa, bbb, ccc, ddd, eee, x[15], 7);
362 III(eee, aaa, bbb, ccc, ddd, x[ 8], 12);
363 III(ddd, eee, aaa, bbb, ccc, x[12], 7);
364 III(ccc, ddd, eee, aaa, bbb, x[ 4], 6);
365 III(bbb, ccc, ddd, eee, aaa, x[ 9], 15);
366 III(aaa, bbb, ccc, ddd, eee, x[ 1], 13);
367 III(eee, aaa, bbb, ccc, ddd, x[ 2], 11);
368
369 /* parallel round 3 */
370 HHH(ddd, eee, aaa, bbb, ccc, x[15], 9);
371 HHH(ccc, ddd, eee, aaa, bbb, x[ 5], 7);
372 HHH(bbb, ccc, ddd, eee, aaa, x[ 1], 15);
373 HHH(aaa, bbb, ccc, ddd, eee, x[ 3], 11);
374 HHH(eee, aaa, bbb, ccc, ddd, x[ 7], 8);
375 HHH(ddd, eee, aaa, bbb, ccc, x[14], 6);
376 HHH(ccc, ddd, eee, aaa, bbb, x[ 6], 6);
377 HHH(bbb, ccc, ddd, eee, aaa, x[ 9], 14);
378 HHH(aaa, bbb, ccc, ddd, eee, x[11], 12);
379 HHH(eee, aaa, bbb, ccc, ddd, x[ 8], 13);
380 HHH(ddd, eee, aaa, bbb, ccc, x[12], 5);
381 HHH(ccc, ddd, eee, aaa, bbb, x[ 2], 14);
382 HHH(bbb, ccc, ddd, eee, aaa, x[10], 13);
383 HHH(aaa, bbb, ccc, ddd, eee, x[ 0], 13);
384 HHH(eee, aaa, bbb, ccc, ddd, x[ 4], 7);
385 HHH(ddd, eee, aaa, bbb, ccc, x[13], 5);
386
387 /* parallel round 4 */
388 GGG(ccc, ddd, eee, aaa, bbb, x[ 8], 15);
389 GGG(bbb, ccc, ddd, eee, aaa, x[ 6], 5);
390 GGG(aaa, bbb, ccc, ddd, eee, x[ 4], 8);
391 GGG(eee, aaa, bbb, ccc, ddd, x[ 1], 11);
392 GGG(ddd, eee, aaa, bbb, ccc, x[ 3], 14);
393 GGG(ccc, ddd, eee, aaa, bbb, x[11], 14);
394 GGG(bbb, ccc, ddd, eee, aaa, x[15], 6);
395 GGG(aaa, bbb, ccc, ddd, eee, x[ 0], 14);
396 GGG(eee, aaa, bbb, ccc, ddd, x[ 5], 6);
397 GGG(ddd, eee, aaa, bbb, ccc, x[12], 9);
398 GGG(ccc, ddd, eee, aaa, bbb, x[ 2], 12);
399 GGG(bbb, ccc, ddd, eee, aaa, x[13], 9);
400 GGG(aaa, bbb, ccc, ddd, eee, x[ 9], 12);
401 GGG(eee, aaa, bbb, ccc, ddd, x[ 7], 5);
402 GGG(ddd, eee, aaa, bbb, ccc, x[10], 15);
403 GGG(ccc, ddd, eee, aaa, bbb, x[14], 8);
404
405 /* parallel round 5 */
406 FFF(bbb, ccc, ddd, eee, aaa, x[12] , 8);
407 FFF(aaa, bbb, ccc, ddd, eee, x[15] , 5);
408 FFF(eee, aaa, bbb, ccc, ddd, x[10] , 12);
409 FFF(ddd, eee, aaa, bbb, ccc, x[ 4] , 9);
410 FFF(ccc, ddd, eee, aaa, bbb, x[ 1] , 12);
411 FFF(bbb, ccc, ddd, eee, aaa, x[ 5] , 5);
412 FFF(aaa, bbb, ccc, ddd, eee, x[ 8] , 14);
413 FFF(eee, aaa, bbb, ccc, ddd, x[ 7] , 6);
414 FFF(ddd, eee, aaa, bbb, ccc, x[ 6] , 8);
415 FFF(ccc, ddd, eee, aaa, bbb, x[ 2] , 13);
416 FFF(bbb, ccc, ddd, eee, aaa, x[13] , 6);
417 FFF(aaa, bbb, ccc, ddd, eee, x[14] , 5);
418 FFF(eee, aaa, bbb, ccc, ddd, x[ 0] , 15);
419 FFF(ddd, eee, aaa, bbb, ccc, x[ 3] , 13);
420 FFF(ccc, ddd, eee, aaa, bbb, x[ 9] , 11);
421 FFF(bbb, ccc, ddd, eee, aaa, x[11] , 11);
422
423 /* combine results */
424 ddd += cc + _state[1]; /* final result for _state[0] */
425 _state[1] = _state[2] + dd + eee;
426 _state[2] = _state[3] + ee + aaa;
427 _state[3] = _state[4] + aa + bbb;
428 _state[4] = _state[0] + bb + ccc;
429 _state[0] = ddd;
430
431 //Zeroize sensitive information.
432 x[] = 0;
433 }
434
435 public:
436 enum blockSize = 512;
437
438 /**
439 * Use this to feed the digest with data.
440 * Also implements the $(REF isOutputRange, std,range,primitives)
5fee5ec3 441 * interface for `ubyte` and `const(ubyte)[]`.
b4c522fa
IB
442 *
443 * Example:
444 * ----
445 * RIPEMD160 dig;
446 * dig.put(cast(ubyte) 0); //single ubyte
447 * dig.put(cast(ubyte) 0, cast(ubyte) 0); //variadic
448 * ubyte[10] buf;
449 * dig.put(buf); //buffer
450 * ----
451 */
452 void put(scope const(ubyte)[] data...) @trusted pure nothrow @nogc
453 {
454 uint i, index, partLen;
455 auto inputLen = data.length;
456
457 //Compute number of bytes mod 64
458 index = (cast(uint)_count >> 3) & (64 - 1);
459
460 //Update number of bits
461 _count += inputLen * 8;
462
463 partLen = 64 - index;
464
465 //Transform as many times as possible
466 if (inputLen >= partLen)
467 {
468 (&_buffer[index])[0 .. partLen] = data.ptr[0 .. partLen];
469 transform(&_buffer);
470
471 for (i = partLen; i + 63 < inputLen; i += 64)
472 {
473 transform(cast(const(ubyte[64])*)(data[i .. i + 64].ptr));
474 }
475
476 index = 0;
477 }
478 else
479 {
480 i = 0;
481 }
482
483 /* Buffer remaining input */
484 if (inputLen - i)
485 (&_buffer[index])[0 .. inputLen-i] = (&data[i])[0 .. inputLen-i];
486 }
487
488 /**
489 * Used to (re)initialize the RIPEMD160 digest.
490 *
491 * Note:
492 * For this RIPEMD160 Digest implementation calling start after default construction
493 * is not necessary. Calling start is only necessary to reset the Digest.
494 *
495 * Generic code which deals with different Digest types should always call start though.
496 *
497 * Example:
498 * --------
499 * RIPEMD160 digest;
500 * //digest.start(); //Not necessary
501 * digest.put(0);
502 * --------
503 */
504 void start() @safe pure nothrow @nogc
505 {
506 this = RIPEMD160.init;
507 }
508
509 /**
510 * Returns the finished RIPEMD160 hash. This also calls $(LREF start) to
511 * reset the internal state.
512 *
513 * Example:
514 * --------
515 * //Simple example
516 * RIPEMD160 hash;
517 * hash.start();
518 * hash.put(cast(ubyte) 0);
519 * ubyte[20] result = hash.finish();
520 * assert(toHexString(result) == "C81B94933420221A7AC004A90242D8B1D3E5070D");
521 * --------
522 */
523 ubyte[20] finish() @trusted pure nothrow @nogc
524 {
525 import std.bitmanip : nativeToLittleEndian;
526
527 ubyte[20] data = void;
528 ubyte[8] bits = void;
529 uint index, padLen;
530
531 //Save number of bits
532 bits[0 .. 8] = nativeToLittleEndian(_count)[];
533
534 //Pad out to 56 mod 64
535 index = (cast(uint)_count >> 3) & (64 - 1);
536 padLen = (index < 56) ? (56 - index) : (120 - index);
537 put(_padding[0 .. padLen]);
538
539 //Append length (before padding)
540 put(bits);
541
542 //Store state in digest
543 data[0 .. 4] = nativeToLittleEndian(_state[0])[];
544 data[4 .. 8] = nativeToLittleEndian(_state[1])[];
545 data[8 .. 12] = nativeToLittleEndian(_state[2])[];
546 data[12 .. 16] = nativeToLittleEndian(_state[3])[];
547 data[16 .. 20] = nativeToLittleEndian(_state[4])[];
548
549 /* Zeroize sensitive information. */
550 start();
551 return data;
552 }
553}
554
555///
556@safe unittest
557{
558 //Simple example, hashing a string using ripemd160Of helper function
559 ubyte[20] hash = ripemd160Of("abc");
560 //Let's get a hash string
561 assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC");
562}
563
564///
565@safe unittest
566{
567 //Using the basic API
568 RIPEMD160 hash;
569 hash.start();
570 ubyte[1024] data;
571 //Initialize data here...
572 hash.put(data);
573 ubyte[20] result = hash.finish();
574}
575
576///
577@safe unittest
578{
579 //Let's use the template features:
580 void doSomething(T)(ref T hash)
581 if (isDigest!T)
582 {
583 hash.put(cast(ubyte) 0);
584 }
585 RIPEMD160 md;
586 md.start();
587 doSomething(md);
588 assert(toHexString(md.finish()) == "C81B94933420221A7AC004A90242D8B1D3E5070D");
589}
590
591///
592@safe unittest
593{
594 //Simple example
595 RIPEMD160 hash;
596 hash.start();
597 hash.put(cast(ubyte) 0);
598 ubyte[20] result = hash.finish();
599 assert(toHexString(result) == "C81B94933420221A7AC004A90242D8B1D3E5070D");
600}
601
602@safe unittest
603{
604 assert(isDigest!RIPEMD160);
605}
606
607@system unittest
608{
5fee5ec3 609 import std.conv : hexString;
b4c522fa
IB
610 import std.range;
611
612 ubyte[20] digest;
613
614 RIPEMD160 md;
615 md.put(cast(ubyte[])"abcdef");
616 md.start();
617 md.put(cast(ubyte[])"");
5fee5ec3 618 assert(md.finish() == cast(ubyte[]) hexString!"9c1185a5c5e9fc54612808977ee8f548b2258d31");
b4c522fa
IB
619
620 digest = ripemd160Of("");
5fee5ec3 621 assert(digest == cast(ubyte[]) hexString!"9c1185a5c5e9fc54612808977ee8f548b2258d31");
b4c522fa
IB
622
623 digest = ripemd160Of("a");
5fee5ec3 624 assert(digest == cast(ubyte[]) hexString!"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe");
b4c522fa
IB
625
626 digest = ripemd160Of("abc");
5fee5ec3 627 assert(digest == cast(ubyte[]) hexString!"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc");
b4c522fa
IB
628
629 digest = ripemd160Of("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
5fee5ec3 630 assert(digest == cast(ubyte[]) hexString!"12a053384a9c0c88e405a06c27dcf49ada62eb2b");
b4c522fa
IB
631
632 digest = ripemd160Of("message digest");
5fee5ec3 633 assert(digest == cast(ubyte[]) hexString!"5d0689ef49d2fae572b881b123a85ffa21595f36");
b4c522fa
IB
634
635 digest = ripemd160Of("abcdefghijklmnopqrstuvwxyz");
5fee5ec3 636 assert(digest == cast(ubyte[]) hexString!"f71c27109c692c1b56bbdceb5b9d2865b3708dbc");
b4c522fa
IB
637
638 digest = ripemd160Of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
5fee5ec3 639 assert(digest == cast(ubyte[]) hexString!"b0e20b6e3116640286ed3a87a5713079b21f5189");
b4c522fa
IB
640
641 digest = ripemd160Of("1234567890123456789012345678901234567890"~
642 "1234567890123456789012345678901234567890");
5fee5ec3 643 assert(digest == cast(ubyte[]) hexString!"9b752e45573d4b39f4dbd3323cab82bf63326bfb");
b4c522fa 644
5fee5ec3
IB
645 enum ubyte[20] input = cast(ubyte[20]) hexString!"f71c27109c692c1b56bbdceb5b9d2865b3708dbc";
646 assert(toHexString(input)
b4c522fa
IB
647 == "F71C27109C692C1B56BBDCEB5B9D2865B3708DBC");
648
649 ubyte[] onemilliona = new ubyte[1000000];
650 onemilliona[] = 'a';
651 digest = ripemd160Of(onemilliona);
5fee5ec3 652 assert(digest == cast(ubyte[]) hexString!"52783243c1697bdbe16d37f97f68f08325dc1528");
b4c522fa
IB
653
654 auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000);
655 digest = ripemd160Of(oneMillionRange);
5fee5ec3 656 assert(digest == cast(ubyte[]) hexString!"52783243c1697bdbe16d37f97f68f08325dc1528");
b4c522fa
IB
657}
658
659/**
660 * This is a convenience alias for $(REF digest, std,digest) using the
661 * RIPEMD160 implementation.
662 */
663//simple alias doesn't work here, hope this gets inlined...
664auto ripemd160Of(T...)(T data)
665{
666 return digest!(RIPEMD160, T)(data);
667}
668
669///
670@safe unittest
671{
672 ubyte[20] hash = ripemd160Of("abc");
673 assert(hash == digest!RIPEMD160("abc"));
674}
675
676/**
677 * OOP API RIPEMD160 implementation.
5fee5ec3 678 * See `std.digest` for differences between template and OOP API.
b4c522fa
IB
679 *
680 * This is an alias for $(D $(REF WrapperDigest, std,digest)!RIPEMD160),
681 * see there for more information.
682 */
683alias RIPEMD160Digest = WrapperDigest!RIPEMD160;
684
685///
686@safe unittest
687{
688 //Simple example, hashing a string using Digest.digest helper function
689 auto md = new RIPEMD160Digest();
690 ubyte[] hash = md.digest("abc");
691 //Let's get a hash string
692 assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC");
693}
694
695///
696@system unittest
697{
698 //Let's use the OOP features:
699 void test(Digest dig)
700 {
701 dig.put(cast(ubyte) 0);
702 }
703 auto md = new RIPEMD160Digest();
704 test(md);
705
706 //Let's use a custom buffer:
707 ubyte[20] buf;
708 ubyte[] result = md.finish(buf[]);
709 assert(toHexString(result) == "C81B94933420221A7AC004A90242D8B1D3E5070D");
710}
711
712@system unittest
713{
5fee5ec3 714 import std.conv : hexString;
b4c522fa
IB
715 auto md = new RIPEMD160Digest();
716
717 md.put(cast(ubyte[])"abcdef");
718 md.reset();
719 md.put(cast(ubyte[])"");
5fee5ec3 720 assert(md.finish() == cast(ubyte[]) hexString!"9c1185a5c5e9fc54612808977ee8f548b2258d31");
b4c522fa
IB
721
722 md.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
723 ubyte[20] result;
724 auto result2 = md.finish(result[]);
5fee5ec3 725 assert(result[0 .. 20] == result2 && result2 == cast(ubyte[]) hexString!"f71c27109c692c1b56bbdceb5b9d2865b3708dbc");
b4c522fa
IB
726
727 debug
728 {
729 import std.exception;
730 assertThrown!Error(md.finish(result[0 .. 19]));
731 }
732
733 assert(md.length == 20);
734
5fee5ec3 735 assert(md.digest("") == cast(ubyte[]) hexString!"9c1185a5c5e9fc54612808977ee8f548b2258d31");
b4c522fa 736
5fee5ec3 737 assert(md.digest("a") == cast(ubyte[]) hexString!"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe");
b4c522fa 738
5fee5ec3 739 assert(md.digest("abc") == cast(ubyte[]) hexString!"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc");
b4c522fa
IB
740
741 assert(md.digest("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
5fee5ec3 742 == cast(ubyte[]) hexString!"12a053384a9c0c88e405a06c27dcf49ada62eb2b");
b4c522fa 743
5fee5ec3 744 assert(md.digest("message digest") == cast(ubyte[]) hexString!"5d0689ef49d2fae572b881b123a85ffa21595f36");
b4c522fa
IB
745
746 assert(md.digest("abcdefghijklmnopqrstuvwxyz")
5fee5ec3 747 == cast(ubyte[]) hexString!"f71c27109c692c1b56bbdceb5b9d2865b3708dbc");
b4c522fa
IB
748
749 assert(md.digest("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
5fee5ec3 750 == cast(ubyte[]) hexString!"b0e20b6e3116640286ed3a87a5713079b21f5189");
b4c522fa
IB
751
752 assert(md.digest("1234567890123456789012345678901234567890",
753 "1234567890123456789012345678901234567890")
5fee5ec3 754 == cast(ubyte[]) hexString!"9b752e45573d4b39f4dbd3323cab82bf63326bfb");
b4c522fa
IB
755
756 assert(md.digest(new ubyte[160/8]) // 160 zero bits
5fee5ec3 757 == cast(ubyte[]) hexString!"5c00bd4aca04a9057c09b20b05f723f2e23deb65");
b4c522fa 758}