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