1 /******************************************************************************* 2 3 This module implements the Ripemd160 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.Ripemd160; 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 Ripemd160 : MerkleDamgard 43 { 44 private uint[5] context; 45 private static immutable uint padChar = 0x80; 46 47 /*********************************************************************** 48 49 ***********************************************************************/ 50 51 private static const(uint[5]) initial = 52 [ 53 0x67452301, 54 0xefcdab89, 55 0x98badcfe, 56 0x10325476, 57 0xc3d2e1f0 58 ]; 59 60 /*********************************************************************** 61 62 Construct a Ripemd160 63 64 ***********************************************************************/ 65 66 this() { } 67 68 /*********************************************************************** 69 70 The size of a Ripemd160 digest is 20 bytes 71 72 ***********************************************************************/ 73 74 override uint digestSize() {return 20;} 75 76 77 /*********************************************************************** 78 79 Initialize the cipher 80 81 Remarks: 82 Returns the cipher state to it's initial value 83 84 ***********************************************************************/ 85 86 override void reset() 87 { 88 super.reset(); 89 context[] = initial[]; 90 } 91 92 /*********************************************************************** 93 94 Obtain the digest 95 96 Returns: 97 the digest 98 99 Remarks: 100 Returns a digest of the current cipher state, this may be the 101 final digest, or a digest of the state between calls to update() 102 103 ***********************************************************************/ 104 105 override void createDigest(ubyte[] buf) 106 { 107 version (BigEndian) 108 ByteSwap.swap32 (context.ptr, context.length * uint.sizeof); 109 110 buf[] = cast(ubyte[]) context; 111 } 112 113 114 /*********************************************************************** 115 116 block size 117 118 Returns: 119 the block size 120 121 Remarks: 122 Specifies the size (in bytes) of the block of data to pass to 123 each call to transform(). For Ripemd160 the blockSize is 64. 124 125 ***********************************************************************/ 126 127 protected override uint blockSize() { return 64; } 128 129 /*********************************************************************** 130 131 Length padding size 132 133 Returns: 134 the length padding size 135 136 Remarks: 137 Specifies the size (in bytes) of the padding which uses the 138 length of the data which has been ciphered, this padding is 139 carried out by the padLength method. For Ripemd160 the addSize is 8. 140 141 ***********************************************************************/ 142 143 protected override uint addSize() { return 8; } 144 145 /*********************************************************************** 146 147 Pads the cipher data 148 149 Params: 150 at = a slice of the cipher buffer to fill with padding 151 152 Remarks: 153 Fills the passed buffer slice with the appropriate padding for 154 the final call to transform(). This padding will fill the cipher 155 buffer up to blockSize()-addSize(). 156 157 ***********************************************************************/ 158 159 protected override void padMessage(ubyte[] at) 160 { 161 at[0] = padChar; 162 at[1..at.length] = 0; 163 } 164 165 /*********************************************************************** 166 167 Performs the length padding 168 169 Params: 170 at = the slice of the cipher buffer to fill with padding 171 length = the length of the data which has been ciphered 172 173 Remarks: 174 Fills the passed buffer slice with addSize() bytes of padding 175 based on the length in bytes of the input data which has been 176 ciphered. 177 178 ***********************************************************************/ 179 180 protected override void padLength(ubyte[] at, ulong length) 181 { 182 length <<= 3; 183 littleEndian64((cast(ubyte*)&length)[0..8],cast(ulong[]) at); 184 } 185 186 /*********************************************************************** 187 188 Performs the cipher on a block of data 189 190 Params: 191 input = the block of data to cipher 192 193 Remarks: 194 The actual cipher algorithm is carried out by this method on 195 the passed block of data. This method is called for every 196 blockSize() bytes of input data and once more with the remaining 197 data padded to blockSize(). 198 199 ***********************************************************************/ 200 201 protected override void transform(ubyte[] input) 202 { 203 uint al, bl, cl, dl, el; 204 uint ar, br, cr, dr, er; 205 uint[16] x; 206 207 littleEndian32(input,x); 208 209 al = ar = context[0]; 210 bl = br = context[1]; 211 cl = cr = context[2]; 212 dl = dr = context[3]; 213 el = er = context[4]; 214 215 // Round 1 and parallel round 1 216 al = rotateLeft(al + (bl ^ cl ^ dl) + x[0], 11) + el; 217 ar = rotateLeft(ar + (br ^ (cr | ~dr)) + x[5] + 0x50a28be6, 8) + er; 218 cl = rotateLeft(cl, 10); 219 cr = rotateLeft(cr, 10); 220 el = rotateLeft(el + (al ^ bl ^ cl) + x[1], 14) + dl; 221 er = rotateLeft(er + (ar ^ (br | ~cr)) + x[14] + 0x50a28be6, 9) + dr; 222 bl = rotateLeft(bl, 10); 223 br = rotateLeft(br, 10); 224 dl = rotateLeft(dl + (el ^ al ^ bl) + x[2], 15) + cl; 225 dr = rotateLeft(dr + (er ^ (ar | ~br)) + x[7] + 0x50a28be6, 9) + cr; 226 al = rotateLeft(al, 10); 227 ar = rotateLeft(ar, 10); 228 cl = rotateLeft(cl + (dl ^ el ^ al) + x[3], 12) + bl; 229 cr = rotateLeft(cr + (dr ^ (er | ~ar)) + x[0] + 0x50a28be6, 11) + br; 230 el = rotateLeft(el, 10); 231 er = rotateLeft(er, 10); 232 bl = rotateLeft(bl + (cl ^ dl ^ el) + x[4], 5) + al; 233 br = rotateLeft(br + (cr ^ (dr | ~er)) + x[9] + 0x50a28be6, 13) + ar; 234 dl = rotateLeft(dl, 10); 235 dr = rotateLeft(dr, 10); 236 al = rotateLeft(al + (bl ^ cl ^ dl) + x[5], 8) + el; 237 ar = rotateLeft(ar + (br ^ (cr | ~dr)) + x[2] + 0x50a28be6, 15) + er; 238 cl = rotateLeft(cl, 10); 239 cr = rotateLeft(cr, 10); 240 el = rotateLeft(el + (al ^ bl ^ cl) + x[6], 7) + dl; 241 er = rotateLeft(er + (ar ^ (br | ~cr)) + x[11] + 0x50a28be6, 15) + dr; 242 bl = rotateLeft(bl, 10); 243 br = rotateLeft(br, 10); 244 dl = rotateLeft(dl + (el ^ al ^ bl) + x[7], 9) + cl; 245 dr = rotateLeft(dr + (er ^ (ar | ~br)) + x[4] + 0x50a28be6, 5) + cr; 246 al = rotateLeft(al, 10); 247 ar = rotateLeft(ar, 10); 248 cl = rotateLeft(cl + (dl ^ el ^ al) + x[8], 11) + bl; 249 cr = rotateLeft(cr + (dr ^ (er | ~ar)) + x[13] + 0x50a28be6, 7) + br; 250 el = rotateLeft(el, 10); 251 er = rotateLeft(er, 10); 252 bl = rotateLeft(bl + (cl ^ dl ^ el) + x[9], 13) + al; 253 br = rotateLeft(br + (cr ^ (dr | ~er)) + x[6] + 0x50a28be6, 7) + ar; 254 dl = rotateLeft(dl, 10); 255 dr = rotateLeft(dr, 10); 256 al = rotateLeft(al + (bl ^ cl ^ dl) + x[10], 14) + el; 257 ar = rotateLeft(ar + (br ^ (cr | ~dr)) + x[15] + 0x50a28be6, 8) + er; 258 cl = rotateLeft(cl, 10); 259 cr = rotateLeft(cr, 10); 260 el = rotateLeft(el + (al ^ bl ^ cl) + x[11], 15) + dl; 261 er = rotateLeft(er + (ar ^ (br | ~cr)) + x[8] + 0x50a28be6, 11) + dr; 262 bl = rotateLeft(bl, 10); 263 br = rotateLeft(br, 10); 264 dl = rotateLeft(dl + (el ^ al ^ bl) + x[12], 6) + cl; 265 dr = rotateLeft(dr + (er ^ (ar | ~br)) + x[1] + 0x50a28be6, 14) + cr; 266 al = rotateLeft(al, 10); 267 ar = rotateLeft(ar, 10); 268 cl = rotateLeft(cl + (dl ^ el ^ al) + x[13], 7) + bl; 269 cr = rotateLeft(cr + (dr ^ (er | ~ar)) + x[10] + 0x50a28be6, 14) + br; 270 el = rotateLeft(el, 10); 271 er = rotateLeft(er, 10); 272 bl = rotateLeft(bl + (cl ^ dl ^ el) + x[14], 9) + al; 273 br = rotateLeft(br + (cr ^ (dr | ~er)) + x[3] + 0x50a28be6, 12) + ar; 274 dl = rotateLeft(dl, 10); 275 dr = rotateLeft(dr, 10); 276 al = rotateLeft(al + (bl ^ cl ^ dl) + x[15], 8) + el; 277 ar = rotateLeft(ar + (br ^ (cr | ~dr)) + x[12] + 0x50a28be6, 6) + er; 278 cl = rotateLeft(cl, 10); 279 cr = rotateLeft(cr, 10); 280 281 // Round 2 and parallel round 2 282 el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[7] + 0x5a827999, 7) + dl; 283 er = rotateLeft(er + ((ar & cr) | (br & ~cr)) + x[6] + 0x5c4dd124, 9) + dr; 284 bl = rotateLeft(bl, 10); 285 br = rotateLeft(br, 10); 286 dl = rotateLeft(dl + (((al ^ bl) & el) ^ bl) + x[4] + 0x5a827999, 6) + cl; 287 dr = rotateLeft(dr + ((er & br) | (ar & ~br)) + x[11] + 0x5c4dd124, 13) + cr; 288 al = rotateLeft(al, 10); 289 ar = rotateLeft(ar, 10); 290 cl = rotateLeft(cl + (((el ^ al) & dl) ^ al) + x[13] + 0x5a827999, 8) + bl; 291 cr = rotateLeft(cr + ((dr & ar) | (er & ~ar)) + x[3] + 0x5c4dd124, 15) + br; 292 el = rotateLeft(el, 10); 293 er = rotateLeft(er, 10); 294 bl = rotateLeft(bl + (((dl ^ el) & cl) ^ el) + x[1] + 0x5a827999, 13) + al; 295 br = rotateLeft(br + ((cr & er) | (dr & ~er)) + x[7] + 0x5c4dd124, 7) + ar; 296 dl = rotateLeft(dl, 10); 297 dr = rotateLeft(dr, 10); 298 al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[10] + 0x5a827999, 11) + el; 299 ar = rotateLeft(ar + ((br & dr) | (cr & ~dr)) + x[0] + 0x5c4dd124, 12) + er; 300 cl = rotateLeft(cl, 10); 301 cr = rotateLeft(cr, 10); 302 el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[6] + 0x5a827999, 9) + dl; 303 er = rotateLeft(er + ((ar & cr) | (br & ~cr)) + x[13] + 0x5c4dd124, 8) + dr; 304 bl = rotateLeft(bl, 10); 305 br = rotateLeft(br, 10); 306 dl = rotateLeft(dl + (((al ^ bl) & el) ^ bl) + x[15] + 0x5a827999, 7) + cl; 307 dr = rotateLeft(dr + ((er & br) | (ar & ~br)) + x[5] + 0x5c4dd124, 9) + cr; 308 al = rotateLeft(al, 10); 309 ar = rotateLeft(ar, 10); 310 cl = rotateLeft(cl + (((el ^ al) & dl) ^ al) + x[3] + 0x5a827999, 15) + bl; 311 cr = rotateLeft(cr + ((dr & ar) | (er & ~ar)) + x[10] + 0x5c4dd124, 11) + br; 312 el = rotateLeft(el, 10); 313 er = rotateLeft(er, 10); 314 bl = rotateLeft(bl + (((dl ^ el) & cl) ^ el) + x[12] + 0x5a827999, 7) + al; 315 br = rotateLeft(br + ((cr & er) | (dr & ~er)) + x[14] + 0x5c4dd124, 7) + ar; 316 dl = rotateLeft(dl, 10); 317 dr = rotateLeft(dr, 10); 318 al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[0] + 0x5a827999, 12) + el; 319 ar = rotateLeft(ar + ((br & dr) | (cr & ~dr)) + x[15] + 0x5c4dd124, 7) + er; 320 cl = rotateLeft(cl, 10); 321 cr = rotateLeft(cr, 10); 322 el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[9] + 0x5a827999, 15) + dl; 323 er = rotateLeft(er + ((ar & cr) | (br & ~cr)) + x[8] + 0x5c4dd124, 12) + dr; 324 bl = rotateLeft(bl, 10); 325 br = rotateLeft(br, 10); 326 dl = rotateLeft(dl + (((al ^ bl) & el) ^ bl) + x[5] + 0x5a827999, 9) + cl; 327 dr = rotateLeft(dr + ((er & br) | (ar & ~br)) + x[12] + 0x5c4dd124, 7) + cr; 328 al = rotateLeft(al, 10); 329 ar = rotateLeft(ar, 10); 330 cl = rotateLeft(cl + (((el ^ al) & dl) ^ al) + x[2] + 0x5a827999, 11) + bl; 331 cr = rotateLeft(cr + ((dr & ar) | (er & ~ar)) + x[4] + 0x5c4dd124, 6) + br; 332 el = rotateLeft(el, 10); 333 er = rotateLeft(er, 10); 334 bl = rotateLeft(bl + (((dl ^ el) & cl) ^ el) + x[14] + 0x5a827999, 7) + al; 335 br = rotateLeft(br + ((cr & er) | (dr & ~er)) + x[9] + 0x5c4dd124, 15) + ar; 336 dl = rotateLeft(dl, 10); 337 dr = rotateLeft(dr, 10); 338 al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[11] + 0x5a827999, 13) + el; 339 ar = rotateLeft(ar + ((br & dr) | (cr & ~dr)) + x[1] + 0x5c4dd124, 13) + er; 340 cl = rotateLeft(cl, 10); 341 cr = rotateLeft(cr, 10); 342 el = rotateLeft(el + (((bl ^ cl) & al) ^ cl) + x[8] + 0x5a827999, 12) + dl; 343 er = rotateLeft(er + ((ar & cr) | (br & ~cr)) + x[2] + 0x5c4dd124, 11) + dr; 344 bl = rotateLeft(bl, 10); 345 br = rotateLeft(br, 10); 346 347 // Round 3 and parallel round 3 348 dl = rotateLeft(dl + ((el | ~al) ^ bl) + x[3] + 0x6ed9eba1, 11) + cl; 349 dr = rotateLeft(dr + ((er | ~ar) ^ br) + x[15] + 0x6d703ef3, 9) + cr; 350 al = rotateLeft(al, 10); 351 ar = rotateLeft(ar, 10); 352 cl = rotateLeft(cl + ((dl | ~el) ^ al) + x[10] + 0x6ed9eba1, 13) + bl; 353 cr = rotateLeft(cr + ((dr | ~er) ^ ar) + x[5] + 0x6d703ef3, 7) + br; 354 el = rotateLeft(el, 10); 355 er = rotateLeft(er, 10); 356 bl = rotateLeft(bl + ((cl | ~dl) ^ el) + x[14] + 0x6ed9eba1, 6) + al; 357 br = rotateLeft(br + ((cr | ~dr) ^ er) + x[1] + 0x6d703ef3, 15) + ar; 358 dl = rotateLeft(dl, 10); 359 dr = rotateLeft(dr, 10); 360 al = rotateLeft(al + ((bl | ~cl) ^ dl) + x[4] + 0x6ed9eba1, 7) + el; 361 ar = rotateLeft(ar + ((br | ~cr) ^ dr) + x[3] + 0x6d703ef3, 11) + er; 362 cl = rotateLeft(cl, 10); 363 cr = rotateLeft(cr, 10); 364 el = rotateLeft(el + ((al | ~bl) ^ cl) + x[9] + 0x6ed9eba1, 14) + dl; 365 er = rotateLeft(er + ((ar | ~br) ^ cr) + x[7] + 0x6d703ef3, 8) + dr; 366 bl = rotateLeft(bl, 10); 367 br = rotateLeft(br, 10); 368 dl = rotateLeft(dl + ((el | ~al) ^ bl) + x[15] + 0x6ed9eba1, 9) + cl; 369 dr = rotateLeft(dr + ((er | ~ar) ^ br) + x[14] + 0x6d703ef3, 6) + cr; 370 al = rotateLeft(al, 10); 371 ar = rotateLeft(ar, 10); 372 cl = rotateLeft(cl + ((dl | ~el) ^ al) + x[8] + 0x6ed9eba1, 13) + bl; 373 cr = rotateLeft(cr + ((dr | ~er) ^ ar) + x[6] + 0x6d703ef3, 6) + br; 374 el = rotateLeft(el, 10); 375 er = rotateLeft(er, 10); 376 bl = rotateLeft(bl + ((cl | ~dl) ^ el) + x[1] + 0x6ed9eba1, 15) + al; 377 br = rotateLeft(br + ((cr | ~dr) ^ er) + x[9] + 0x6d703ef3, 14) + ar; 378 dl = rotateLeft(dl, 10); 379 dr = rotateLeft(dr, 10); 380 al = rotateLeft(al + ((bl | ~cl) ^ dl) + x[2] + 0x6ed9eba1, 14) + el; 381 ar = rotateLeft(ar + ((br | ~cr) ^ dr) + x[11] + 0x6d703ef3, 12) + er; 382 cl = rotateLeft(cl, 10); 383 cr = rotateLeft(cr, 10); 384 el = rotateLeft(el + ((al | ~bl) ^ cl) + x[7] + 0x6ed9eba1, 8) + dl; 385 er = rotateLeft(er + ((ar | ~br) ^ cr) + x[8] + 0x6d703ef3, 13) + dr; 386 bl = rotateLeft(bl, 10); 387 br = rotateLeft(br, 10); 388 dl = rotateLeft(dl + ((el | ~al) ^ bl) + x[0] + 0x6ed9eba1, 13) + cl; 389 dr = rotateLeft(dr + ((er | ~ar) ^ br) + x[12] + 0x6d703ef3, 5) + cr; 390 al = rotateLeft(al, 10); 391 ar = rotateLeft(ar, 10); 392 cl = rotateLeft(cl + ((dl | ~el) ^ al) + x[6] + 0x6ed9eba1, 6) + bl; 393 cr = rotateLeft(cr + ((dr | ~er) ^ ar) + x[2] + 0x6d703ef3, 14) + br; 394 el = rotateLeft(el, 10); 395 er = rotateLeft(er, 10); 396 bl = rotateLeft(bl + ((cl | ~dl) ^ el) + x[13] + 0x6ed9eba1, 5) + al; 397 br = rotateLeft(br + ((cr | ~dr) ^ er) + x[10] + 0x6d703ef3, 13) + ar; 398 dl = rotateLeft(dl, 10); 399 dr = rotateLeft(dr, 10); 400 al = rotateLeft(al + ((bl | ~cl) ^ dl) + x[11] + 0x6ed9eba1, 12) + el; 401 ar = rotateLeft(ar + ((br | ~cr) ^ dr) + x[0] + 0x6d703ef3, 13) + er; 402 cl = rotateLeft(cl, 10); 403 cr = rotateLeft(cr, 10); 404 el = rotateLeft(el + ((al | ~bl) ^ cl) + x[5] + 0x6ed9eba1, 7) + dl; 405 er = rotateLeft(er + ((ar | ~br) ^ cr) + x[4] + 0x6d703ef3, 7) + dr; 406 bl = rotateLeft(bl, 10); 407 br = rotateLeft(br, 10); 408 dl = rotateLeft(dl + ((el | ~al) ^ bl) + x[12] + 0x6ed9eba1, 5) + cl; 409 dr = rotateLeft(dr + ((er | ~ar) ^ br) + x[13] + 0x6d703ef3, 5) + cr; 410 al = rotateLeft(al, 10); 411 ar = rotateLeft(ar, 10); 412 413 // Round 4 and parallel round 4 414 cl = rotateLeft(cl + ((dl & al) | (el & ~al)) + x[1] + 0x8f1bbcdc, 11) + bl; 415 cr = rotateLeft(cr + (((er ^ ar) & dr) ^ ar) + x[8] + 0x7a6d76e9, 15) + br; 416 el = rotateLeft(el, 10); 417 er = rotateLeft(er, 10); 418 bl = rotateLeft(bl + ((cl & el) | (dl & ~el)) + x[9] + 0x8f1bbcdc, 12) + al; 419 br = rotateLeft(br + (((dr ^ er) & cr) ^ er) + x[6] + 0x7a6d76e9, 5) + ar; 420 dl = rotateLeft(dl, 10); 421 dr = rotateLeft(dr, 10); 422 al = rotateLeft(al + ((bl & dl) | (cl & ~dl)) + x[11] + 0x8f1bbcdc, 14) + el; 423 ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[4] + 0x7a6d76e9, 8) + er; 424 cl = rotateLeft(cl, 10); 425 cr = rotateLeft(cr, 10); 426 el = rotateLeft(el + ((al & cl) | (bl & ~cl)) + x[10] + 0x8f1bbcdc, 15) + dl; 427 er = rotateLeft(er + (((br ^ cr) & ar) ^ cr) + x[1] + 0x7a6d76e9, 11) + dr; 428 bl = rotateLeft(bl, 10); 429 br = rotateLeft(br, 10); 430 dl = rotateLeft(dl + ((el & bl) | (al & ~bl)) + x[0] + 0x8f1bbcdc, 14) + cl; 431 dr = rotateLeft(dr + (((ar ^ br) & er) ^ br) + x[3] + 0x7a6d76e9, 14) + cr; 432 al = rotateLeft(al, 10); 433 ar = rotateLeft(ar, 10); 434 cl = rotateLeft(cl + ((dl & al) | (el & ~al)) + x[8] + 0x8f1bbcdc, 15) + bl; 435 cr = rotateLeft(cr + (((er ^ ar) & dr) ^ ar) + x[11] + 0x7a6d76e9, 14) + br; 436 el = rotateLeft(el, 10); 437 er = rotateLeft(er, 10); 438 bl = rotateLeft(bl + ((cl & el) | (dl & ~el)) + x[12] + 0x8f1bbcdc, 9) + al; 439 br = rotateLeft(br + (((dr ^ er) & cr) ^ er) + x[15] + 0x7a6d76e9, 6) + ar; 440 dl = rotateLeft(dl, 10); 441 dr = rotateLeft(dr, 10); 442 al = rotateLeft(al + ((bl & dl) | (cl & ~dl)) + x[4] + 0x8f1bbcdc, 8) + el; 443 ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[0] + 0x7a6d76e9, 14) + er; 444 cl = rotateLeft(cl, 10); 445 cr = rotateLeft(cr, 10); 446 el = rotateLeft(el + ((al & cl) | (bl & ~cl)) + x[13] + 0x8f1bbcdc, 9) + dl; 447 er = rotateLeft(er + (((br ^ cr) & ar) ^ cr) + x[5] + 0x7a6d76e9, 6) + dr; 448 bl = rotateLeft(bl, 10); 449 br = rotateLeft(br, 10); 450 dl = rotateLeft(dl + ((el & bl) | (al & ~bl)) + x[3] + 0x8f1bbcdc, 14) + cl; 451 dr = rotateLeft(dr + (((ar ^ br) & er) ^ br) + x[12] + 0x7a6d76e9, 9) + cr; 452 al = rotateLeft(al, 10); 453 ar = rotateLeft(ar, 10); 454 cl = rotateLeft(cl + ((dl & al) | (el & ~al)) + x[7] + 0x8f1bbcdc, 5) + bl; 455 cr = rotateLeft(cr + (((er ^ ar) & dr) ^ ar) + x[2] + 0x7a6d76e9, 12) + br; 456 el = rotateLeft(el, 10); 457 er = rotateLeft(er, 10); 458 bl = rotateLeft(bl + ((cl & el) | (dl & ~el)) + x[15] + 0x8f1bbcdc, 6) + al; 459 br = rotateLeft(br + (((dr ^ er) & cr) ^ er) + x[13] + 0x7a6d76e9, 9) + ar; 460 dl = rotateLeft(dl, 10); 461 dr = rotateLeft(dr, 10); 462 al = rotateLeft(al + ((bl & dl) | (cl & ~dl)) + x[14] + 0x8f1bbcdc, 8) + el; 463 ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[9] + 0x7a6d76e9, 12) + er; 464 cl = rotateLeft(cl, 10); 465 cr = rotateLeft(cr, 10); 466 el = rotateLeft(el + ((al & cl) | (bl & ~cl)) + x[5] + 0x8f1bbcdc, 6) + dl; 467 er = rotateLeft(er + (((br ^ cr) & ar) ^ cr) + x[7] + 0x7a6d76e9, 5) + dr; 468 bl = rotateLeft(bl, 10); 469 br = rotateLeft(br, 10); 470 dl = rotateLeft(dl + ((el & bl) | (al & ~bl)) + x[6] + 0x8f1bbcdc, 5) + cl; 471 dr = rotateLeft(dr + (((ar ^ br) & er) ^ br) + x[10] + 0x7a6d76e9, 15) + cr; 472 al = rotateLeft(al, 10); 473 ar = rotateLeft(ar, 10); 474 cl = rotateLeft(cl + ((dl & al) | (el & ~al)) + x[2] + 0x8f1bbcdc, 12) + bl; 475 cr = rotateLeft(cr + (((er ^ ar) & dr) ^ ar) + x[14] + 0x7a6d76e9, 8) + br; 476 el = rotateLeft(el, 10); 477 er = rotateLeft(er, 10); 478 479 // Round 5 and parallel round 5 480 bl = rotateLeft(bl + (cl ^ (dl | ~el)) + x[4] + 0xa953fd4e, 9) + al; 481 br = rotateLeft(br + (cr ^ dr ^ er) + x[12], 8) + ar; 482 dl = rotateLeft(dl, 10); 483 dr = rotateLeft(dr, 10); 484 al = rotateLeft(al + (bl ^ (cl | ~dl)) + x[0] + 0xa953fd4e, 15) + el; 485 ar = rotateLeft(ar + (br ^ cr ^ dr) + x[15], 5) + er; 486 cl = rotateLeft(cl, 10); 487 cr = rotateLeft(cr, 10); 488 el = rotateLeft(el + (al ^ (bl | ~cl)) + x[5] + 0xa953fd4e, 5) + dl; 489 er = rotateLeft(er + (ar ^ br ^ cr) + x[10], 12) + dr; 490 bl = rotateLeft(bl, 10); 491 br = rotateLeft(br, 10); 492 dl = rotateLeft(dl + (el ^ (al | ~bl)) + x[9] + 0xa953fd4e, 11) + cl; 493 dr = rotateLeft(dr + (er ^ ar ^ br) + x[4], 9) + cr; 494 al = rotateLeft(al, 10); 495 ar = rotateLeft(ar, 10); 496 cl = rotateLeft(cl + (dl ^ (el | ~al)) + x[7] + 0xa953fd4e, 6) + bl; 497 cr = rotateLeft(cr + (dr ^ er ^ ar) + x[1], 12) + br; 498 el = rotateLeft(el, 10); 499 er = rotateLeft(er, 10); 500 bl = rotateLeft(bl + (cl ^ (dl | ~el)) + x[12] + 0xa953fd4e, 8) + al; 501 br = rotateLeft(br + (cr ^ dr ^ er) + x[5], 5) + ar; 502 dl = rotateLeft(dl, 10); 503 dr = rotateLeft(dr, 10); 504 al = rotateLeft(al + (bl ^ (cl | ~dl)) + x[2] + 0xa953fd4e, 13) + el; 505 ar = rotateLeft(ar + (br ^ cr ^ dr) + x[8], 14) + er; 506 cl = rotateLeft(cl, 10); 507 cr = rotateLeft(cr, 10); 508 el = rotateLeft(el + (al ^ (bl | ~cl)) + x[10] + 0xa953fd4e, 12) + dl; 509 er = rotateLeft(er + (ar ^ br ^ cr) + x[7], 6) + dr; 510 bl = rotateLeft(bl, 10); 511 br = rotateLeft(br, 10); 512 dl = rotateLeft(dl + (el ^ (al | ~bl)) + x[14] + 0xa953fd4e, 5) + cl; 513 dr = rotateLeft(dr + (er ^ ar ^ br) + x[6], 8) + cr; 514 al = rotateLeft(al, 10); 515 ar = rotateLeft(ar, 10); 516 cl = rotateLeft(cl + (dl ^ (el | ~al)) + x[1] + 0xa953fd4e, 12) + bl; 517 cr = rotateLeft(cr + (dr ^ er ^ ar) + x[2], 13) + br; 518 el = rotateLeft(el, 10); 519 er = rotateLeft(er, 10); 520 bl = rotateLeft(bl + (cl ^ (dl | ~el)) + x[3] + 0xa953fd4e, 13) + al; 521 br = rotateLeft(br + (cr ^ dr ^ er) + x[13], 6) + ar; 522 dl = rotateLeft(dl, 10); 523 dr = rotateLeft(dr, 10); 524 al = rotateLeft(al + (bl ^ (cl | ~dl)) + x[8] + 0xa953fd4e, 14) + el; 525 ar = rotateLeft(ar + (br ^ cr ^ dr) + x[14], 5) + er; 526 cl = rotateLeft(cl, 10); 527 cr = rotateLeft(cr, 10); 528 el = rotateLeft(el + (al ^ (bl | ~cl)) + x[11] + 0xa953fd4e, 11) + dl; 529 er = rotateLeft(er + (ar ^ br ^ cr) + x[0], 15) + dr; 530 bl = rotateLeft(bl, 10); 531 br = rotateLeft(br, 10); 532 dl = rotateLeft(dl + (el ^ (al | ~bl)) + x[6] + 0xa953fd4e, 8) + cl; 533 dr = rotateLeft(dr + (er ^ ar ^ br) + x[3], 13) + cr; 534 al = rotateLeft(al, 10); 535 ar = rotateLeft(ar, 10); 536 cl = rotateLeft(cl + (dl ^ (el | ~al)) + x[15] + 0xa953fd4e, 5) + bl; 537 cr = rotateLeft(cr + (dr ^ er ^ ar) + x[9], 11) + br; 538 el = rotateLeft(el, 10); 539 er = rotateLeft(er, 10); 540 bl = rotateLeft(bl + (cl ^ (dl | ~el)) + x[13] + 0xa953fd4e, 6) + al; 541 br = rotateLeft(br + (cr ^ dr ^ er) + x[11], 11) + ar; 542 dl = rotateLeft(dl, 10); 543 dr = rotateLeft(dr, 10); 544 545 uint t = context[1] + cl + dr; 546 context[1] = context[2] + dl + er; 547 context[2] = context[3] + el + ar; 548 context[3] = context[4] + al + br; 549 context[4] = context[0] + bl + cr; 550 context[0] = t; 551 552 x[] = 0; 553 } 554 } 555 556 /******************************************************************************* 557 558 *******************************************************************************/ 559 560 unittest 561 { 562 static istring[] strings = [ 563 "", 564 "a", 565 "abc", 566 "message digest", 567 "abcdefghijklmnopqrstuvwxyz", 568 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 569 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 570 "12345678901234567890123456789012345678901234567890123456789012345678901234567890" 571 ]; 572 573 static istring[] results = [ 574 "9c1185a5c5e9fc54612808977ee8f548b2258d31", 575 "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", 576 "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", 577 "5d0689ef49d2fae572b881b123a85ffa21595f36", 578 "f71c27109c692c1b56bbdceb5b9d2865b3708dbc", 579 "12a053384a9c0c88e405a06c27dcf49ada62eb2b", 580 "b0e20b6e3116640286ed3a87a5713079b21f5189", 581 "9b752e45573d4b39f4dbd3323cab82bf63326bfb" 582 ]; 583 584 Ripemd160 h = new Ripemd160(); 585 586 foreach (i, s; strings) 587 { 588 h.update(cast(ubyte[]) s); 589 char[] d = h.hexDigest; 590 591 test(d == results[i],":("~s~")("~d~")!=("~results[i]~")"); 592 } 593 594 595 char[] s = new char[1000000]; 596 for (auto i = 0; i < s.length; i++) s[i] = 'a'; 597 auto result = "52783243c1697bdbe16d37f97f68f08325dc1528"; 598 h.update(cast(ubyte[]) s); 599 auto d = h.hexDigest; 600 601 test(d == result,":(1 million times \"a\")("~d~")!=("~result~")"); 602 }