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