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 /** 89 * Template API RIPEMD160 implementation. 90 * See `std.digest` for differences between template and OOP API. 91 */ 92 struct RIPEMD160 93 { 94 import core.bitop : rol; 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; 128 a = rol(a, s) + e; 129 c = rol(c, 10); 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; 136 a = rol(a, s) + e; 137 c = rol(c, 10); 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; 144 a = rol(a, s) + e; 145 c = rol(c, 10); 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; 152 a = rol(a, s) + e; 153 c = rol(c, 10); 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; 160 a = rol(a, s) + e; 161 c = rol(c, 10); 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; 173 a = rol(a, s) + e; 174 c = rol(c, 10); 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; 181 a = rol(a, s) + e; 182 c = rol(c, 10); 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; 189 a = rol(a, s) + e; 190 c = rol(c, 10); 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; 197 a = rol(a, s) + e; 198 c = rol(c, 10); 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; 205 a = rol(a, s) + e; 206 c = rol(c, 10); 207 } 208 209 /* 210 * RIPEMD160 basic transformation. Transforms state based on block. 211 */ 212 213 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) 441 * interface for `ubyte` and `const(ubyte)[]`. 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 { 609 import std.conv : hexString; 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[])""); 618 assert(md.finish() == cast(ubyte[]) hexString!"9c1185a5c5e9fc54612808977ee8f548b2258d31"); 619 620 digest = ripemd160Of(""); 621 assert(digest == cast(ubyte[]) hexString!"9c1185a5c5e9fc54612808977ee8f548b2258d31"); 622 623 digest = ripemd160Of("a"); 624 assert(digest == cast(ubyte[]) hexString!"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"); 625 626 digest = ripemd160Of("abc"); 627 assert(digest == cast(ubyte[]) hexString!"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"); 628 629 digest = ripemd160Of("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); 630 assert(digest == cast(ubyte[]) hexString!"12a053384a9c0c88e405a06c27dcf49ada62eb2b"); 631 632 digest = ripemd160Of("message digest"); 633 assert(digest == cast(ubyte[]) hexString!"5d0689ef49d2fae572b881b123a85ffa21595f36"); 634 635 digest = ripemd160Of("abcdefghijklmnopqrstuvwxyz"); 636 assert(digest == cast(ubyte[]) hexString!"f71c27109c692c1b56bbdceb5b9d2865b3708dbc"); 637 638 digest = ripemd160Of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); 639 assert(digest == cast(ubyte[]) hexString!"b0e20b6e3116640286ed3a87a5713079b21f5189"); 640 641 digest = ripemd160Of("1234567890123456789012345678901234567890"~ 642 "1234567890123456789012345678901234567890"); 643 assert(digest == cast(ubyte[]) hexString!"9b752e45573d4b39f4dbd3323cab82bf63326bfb"); 644 645 enum ubyte[20] input = cast(ubyte[20]) hexString!"f71c27109c692c1b56bbdceb5b9d2865b3708dbc"; 646 assert(toHexString(input) 647 == "F71C27109C692C1B56BBDCEB5B9D2865B3708DBC"); 648 649 ubyte[] onemilliona = new ubyte[1000000]; 650 onemilliona[] = 'a'; 651 digest = ripemd160Of(onemilliona); 652 assert(digest == cast(ubyte[]) hexString!"52783243c1697bdbe16d37f97f68f08325dc1528"); 653 654 auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000); 655 digest = ripemd160Of(oneMillionRange); 656 assert(digest == cast(ubyte[]) hexString!"52783243c1697bdbe16d37f97f68f08325dc1528"); 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... 664 auto 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. 678 * See `std.digest` for differences between template and OOP API. 679 * 680 * This is an alias for $(D $(REF WrapperDigest, std,digest)!RIPEMD160), 681 * see there for more information. 682 */ 683 alias 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 { 714 import std.conv : hexString; 715 auto md = new RIPEMD160Digest(); 716 717 md.put(cast(ubyte[])"abcdef"); 718 md.reset(); 719 md.put(cast(ubyte[])""); 720 assert(md.finish() == cast(ubyte[]) hexString!"9c1185a5c5e9fc54612808977ee8f548b2258d31"); 721 722 md.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz"); 723 ubyte[20] result; 724 auto result2 = md.finish(result[]); 725 assert(result[0 .. 20] == result2 && result2 == cast(ubyte[]) hexString!"f71c27109c692c1b56bbdceb5b9d2865b3708dbc"); 726 727 debug 728 { 729 import std.exception; 730 assertThrown!Error(md.finish(result[0 .. 19])); 731 } 732 733 assert(md.length == 20); 734 735 assert(md.digest("") == cast(ubyte[]) hexString!"9c1185a5c5e9fc54612808977ee8f548b2258d31"); 736 737 assert(md.digest("a") == cast(ubyte[]) hexString!"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe"); 738 739 assert(md.digest("abc") == cast(ubyte[]) hexString!"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"); 740 741 assert(md.digest("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") 742 == cast(ubyte[]) hexString!"12a053384a9c0c88e405a06c27dcf49ada62eb2b"); 743 744 assert(md.digest("message digest") == cast(ubyte[]) hexString!"5d0689ef49d2fae572b881b123a85ffa21595f36"); 745 746 assert(md.digest("abcdefghijklmnopqrstuvwxyz") 747 == cast(ubyte[]) hexString!"f71c27109c692c1b56bbdceb5b9d2865b3708dbc"); 748 749 assert(md.digest("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") 750 == cast(ubyte[]) hexString!"b0e20b6e3116640286ed3a87a5713079b21f5189"); 751 752 assert(md.digest("1234567890123456789012345678901234567890", 753 "1234567890123456789012345678901234567890") 754 == cast(ubyte[]) hexString!"9b752e45573d4b39f4dbd3323cab82bf63326bfb"); 755 756 assert(md.digest(new ubyte[160/8]) // 160 zero bits 757 == cast(ubyte[]) hexString!"5c00bd4aca04a9057c09b20b05f723f2e23deb65"); 758 }