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