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