1 /******************************************************************************* 2 3 This module implements the Ripemd256 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.Ripemd256; 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 Ripemd256 : MerkleDamgard 43 { 44 private uint[8] context; 45 private static immutable uint padChar = 0x80; 46 47 /*********************************************************************** 48 49 ***********************************************************************/ 50 51 private static const(uint[8]) initial = 52 [ 53 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 54 0x76543210, 0xfedcba98, 0x89abcdef, 0x01234567 55 ]; 56 57 /*********************************************************************** 58 59 Construct a Ripemd256 60 61 ***********************************************************************/ 62 63 this() { } 64 65 /*********************************************************************** 66 67 The size of a Ripemd256 digest is 32 bytes 68 69 ***********************************************************************/ 70 71 override uint digestSize() {return 32;} 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 Ripemd256 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 Ripemd256 the addSize is 8. 137 138 ***********************************************************************/ 139 140 protected override 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; 201 uint ar, br, cr, dr; 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 ar = context[4]; 212 br = context[5]; 213 cr = context[6]; 214 dr = context[7]; 215 216 // Round 1 and parallel round 1 217 al = rotateLeft(al + (bl ^ cl ^ dl) + x[0], 11); 218 ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[5] + 0x50a28be6, 8); 219 dl = rotateLeft(dl + (al ^ bl ^ cl) + x[1], 14); 220 dr = rotateLeft(dr + ((ar & cr) | (br & ~(cr))) + x[14] + 0x50a28be6, 9); 221 cl = rotateLeft(cl + (dl ^ al ^ bl) + x[2], 15); 222 cr = rotateLeft(cr + ((dr & br) | (ar & ~(br))) + x[7] + 0x50a28be6, 9); 223 bl = rotateLeft(bl + (cl ^ dl ^ al) + x[3], 12); 224 br = rotateLeft(br + ((cr & ar) | (dr & ~(ar))) + x[0] + 0x50a28be6, 11); 225 al = rotateLeft(al + (bl ^ cl ^ dl) + x[4], 5); 226 ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[9] + 0x50a28be6, 13); 227 dl = rotateLeft(dl + (al ^ bl ^ cl) + x[5], 8); 228 dr = rotateLeft(dr + ((ar & cr) | (br & ~(cr))) + x[2] + 0x50a28be6, 15); 229 cl = rotateLeft(cl + (dl ^ al ^ bl) + x[6], 7); 230 cr = rotateLeft(cr + ((dr & br) | (ar & ~(br))) + x[11] + 0x50a28be6, 15); 231 bl = rotateLeft(bl + (cl ^ dl ^ al) + x[7], 9); 232 br = rotateLeft(br + ((cr & ar) | (dr & ~(ar))) + x[4] + 0x50a28be6, 5); 233 al = rotateLeft(al + (bl ^ cl ^ dl) + x[8], 11); 234 ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[13] + 0x50a28be6, 7); 235 dl = rotateLeft(dl + (al ^ bl ^ cl) + x[9], 13); 236 dr = rotateLeft(dr + ((ar & cr) | (br & ~(cr))) + x[6] + 0x50a28be6, 7); 237 cl = rotateLeft(cl + (dl ^ al ^ bl) + x[10], 14); 238 cr = rotateLeft(cr + ((dr & br) | (ar & ~(br))) + x[15] + 0x50a28be6, 8); 239 bl = rotateLeft(bl + (cl ^ dl ^ al) + x[11], 15); 240 br = rotateLeft(br + ((cr & ar) | (dr & ~(ar))) + x[8] + 0x50a28be6, 11); 241 al = rotateLeft(al + (bl ^ cl ^ dl) + x[12], 6); 242 ar = rotateLeft(ar + ((br & dr) | (cr & ~(dr))) + x[1] + 0x50a28be6, 14); 243 dl = rotateLeft(dl + (al ^ bl ^ cl) + x[13], 7); 244 dr = rotateLeft(dr + ((ar & cr) | (br & ~(cr))) + x[10] + 0x50a28be6, 14); 245 cl = rotateLeft(cl + (dl ^ al ^ bl) + x[14], 9); 246 cr = rotateLeft(cr + ((dr & br) | (ar & ~(br))) + x[3] + 0x50a28be6, 12); 247 bl = rotateLeft(bl + (cl ^ dl ^ al) + x[15], 8); 248 br = rotateLeft(br + ((cr & ar) | (dr & ~(ar))) + x[12] + 0x50a28be6, 6); 249 250 t = al; al = ar; ar = t; 251 252 // Round 2 and parallel round 2 253 al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[7] + 0x5a827999, 7); 254 ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[6] + 0x5c4dd124, 9); 255 dl = rotateLeft(dl + (((bl ^ cl) & al) ^ cl) + x[4] + 0x5a827999, 6); 256 dr = rotateLeft(dr + ((ar | ~(br)) ^ cr) + x[11] + 0x5c4dd124, 13); 257 cl = rotateLeft(cl + (((al ^ bl) & dl) ^ bl) + x[13] + 0x5a827999, 8); 258 cr = rotateLeft(cr + ((dr | ~(ar)) ^ br) + x[3] + 0x5c4dd124, 15); 259 bl = rotateLeft(bl + (((dl ^ al) & cl) ^ al) + x[1] + 0x5a827999, 13); 260 br = rotateLeft(br + ((cr | ~(dr)) ^ ar) + x[7] + 0x5c4dd124, 7); 261 al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[10] + 0x5a827999, 11); 262 ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[0] + 0x5c4dd124, 12); 263 dl = rotateLeft(dl + (((bl ^ cl) & al) ^ cl) + x[6] + 0x5a827999, 9); 264 dr = rotateLeft(dr + ((ar | ~(br)) ^ cr) + x[13] + 0x5c4dd124, 8); 265 cl = rotateLeft(cl + (((al ^ bl) & dl) ^ bl) + x[15] + 0x5a827999, 7); 266 cr = rotateLeft(cr + ((dr | ~(ar)) ^ br) + x[5] + 0x5c4dd124, 9); 267 bl = rotateLeft(bl + (((dl ^ al) & cl) ^ al) + x[3] + 0x5a827999, 15); 268 br = rotateLeft(br + ((cr | ~(dr)) ^ ar) + x[10] + 0x5c4dd124, 11); 269 al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[12] + 0x5a827999, 7); 270 ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[14] + 0x5c4dd124, 7); 271 dl = rotateLeft(dl + (((bl ^ cl) & al) ^ cl) + x[0] + 0x5a827999, 12); 272 dr = rotateLeft(dr + ((ar | ~(br)) ^ cr) + x[15] + 0x5c4dd124, 7); 273 cl = rotateLeft(cl + (((al ^ bl) & dl) ^ bl) + x[9] + 0x5a827999, 15); 274 cr = rotateLeft(cr + ((dr | ~(ar)) ^ br) + x[8] + 0x5c4dd124, 12); 275 bl = rotateLeft(bl + (((dl ^ al) & cl) ^ al) + x[5] + 0x5a827999, 9); 276 br = rotateLeft(br + ((cr | ~(dr)) ^ ar) + x[12] + 0x5c4dd124, 7); 277 al = rotateLeft(al + (((cl ^ dl) & bl) ^ dl) + x[2] + 0x5a827999, 11); 278 ar = rotateLeft(ar + ((br | ~(cr)) ^ dr) + x[4] + 0x5c4dd124, 6); 279 dl = rotateLeft(dl + (((bl ^ cl) & al) ^ cl) + x[14] + 0x5a827999, 7); 280 dr = rotateLeft(dr + ((ar | ~(br)) ^ cr) + x[9] + 0x5c4dd124, 15); 281 cl = rotateLeft(cl + (((al ^ bl) & dl) ^ bl) + x[11] + 0x5a827999, 13); 282 cr = rotateLeft(cr + ((dr | ~(ar)) ^ br) + x[1] + 0x5c4dd124, 13); 283 bl = rotateLeft(bl + (((dl ^ al) & cl) ^ al) + x[8] + 0x5a827999, 12); 284 br = rotateLeft(br + ((cr | ~(dr)) ^ ar) + x[2] + 0x5c4dd124, 11); 285 286 t = bl; bl = br; br = t; 287 288 // Round 3 and parallel round 3 289 al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[3] + 0x6ed9eba1, 11); 290 ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[15] + 0x6d703ef3, 9); 291 dl = rotateLeft(dl + ((al | ~(bl)) ^ cl) + x[10] + 0x6ed9eba1, 13); 292 dr = rotateLeft(dr + (((br ^ cr) & ar) ^ cr) + x[5] + 0x6d703ef3, 7); 293 cl = rotateLeft(cl + ((dl | ~(al)) ^ bl) + x[14] + 0x6ed9eba1, 6); 294 cr = rotateLeft(cr + (((ar ^ br) & dr) ^ br) + x[1] + 0x6d703ef3, 15); 295 bl = rotateLeft(bl + ((cl | ~(dl)) ^ al) + x[4] + 0x6ed9eba1, 7); 296 br = rotateLeft(br + (((dr ^ ar) & cr) ^ ar) + x[3] + 0x6d703ef3, 11); 297 al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[9] + 0x6ed9eba1, 14); 298 ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[7] + 0x6d703ef3, 8); 299 dl = rotateLeft(dl + ((al | ~(bl)) ^ cl) + x[15] + 0x6ed9eba1, 9); 300 dr = rotateLeft(dr + (((br ^ cr) & ar) ^ cr) + x[14] + 0x6d703ef3, 6); 301 cl = rotateLeft(cl + ((dl | ~(al)) ^ bl) + x[8] + 0x6ed9eba1, 13); 302 cr = rotateLeft(cr + (((ar ^ br) & dr) ^ br) + x[6] + 0x6d703ef3, 6); 303 bl = rotateLeft(bl + ((cl | ~(dl)) ^ al) + x[1] + 0x6ed9eba1, 15); 304 br = rotateLeft(br + (((dr ^ ar) & cr) ^ ar) + x[9] + 0x6d703ef3, 14); 305 al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[2] + 0x6ed9eba1, 14); 306 ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[11] + 0x6d703ef3, 12); 307 dl = rotateLeft(dl + ((al | ~(bl)) ^ cl) + x[7] + 0x6ed9eba1, 8); 308 dr = rotateLeft(dr + (((br ^ cr) & ar) ^ cr) + x[8] + 0x6d703ef3, 13); 309 cl = rotateLeft(cl + ((dl | ~(al)) ^ bl) + x[0] + 0x6ed9eba1, 13); 310 cr = rotateLeft(cr + (((ar ^ br) & dr) ^ br) + x[12] + 0x6d703ef3, 5); 311 bl = rotateLeft(bl + ((cl | ~(dl)) ^ al) + x[6] + 0x6ed9eba1, 6); 312 br = rotateLeft(br + (((dr ^ ar) & cr) ^ ar) + x[2] + 0x6d703ef3, 14); 313 al = rotateLeft(al + ((bl | ~(cl)) ^ dl) + x[13] + 0x6ed9eba1, 5); 314 ar = rotateLeft(ar + (((cr ^ dr) & br) ^ dr) + x[10] + 0x6d703ef3, 13); 315 dl = rotateLeft(dl + ((al | ~(bl)) ^ cl) + x[11] + 0x6ed9eba1, 12); 316 dr = rotateLeft(dr + (((br ^ cr) & ar) ^ cr) + x[0] + 0x6d703ef3, 13); 317 cl = rotateLeft(cl + ((dl | ~(al)) ^ bl) + x[5] + 0x6ed9eba1, 7); 318 cr = rotateLeft(cr + (((ar ^ br) & dr) ^ br) + x[4] + 0x6d703ef3, 7); 319 bl = rotateLeft(bl + ((cl | ~(dl)) ^ al) + x[12] + 0x6ed9eba1, 5); 320 br = rotateLeft(br + (((dr ^ ar) & cr) ^ ar) + x[13] + 0x6d703ef3, 5); 321 322 t = cl; cl = cr; cr = t; 323 324 // Round 4 and parallel round 4 325 al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[1] + 0x8f1bbcdc, 11); 326 ar = rotateLeft(ar + (br ^ cr ^ dr) + x[8], 15); 327 dl = rotateLeft(dl + ((al & cl) | (bl & ~(cl))) + x[9] + 0x8f1bbcdc, 12); 328 dr = rotateLeft(dr + (ar ^ br ^ cr) + x[6], 5); 329 cl = rotateLeft(cl + ((dl & bl) | (al & ~(bl))) + x[11] + 0x8f1bbcdc, 14); 330 cr = rotateLeft(cr + (dr ^ ar ^ br) + x[4], 8); 331 bl = rotateLeft(bl + ((cl & al) | (dl & ~(al))) + x[10] + 0x8f1bbcdc, 15); 332 br = rotateLeft(br + (cr ^ dr ^ ar) + x[1], 11); 333 al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[0] + 0x8f1bbcdc, 14); 334 ar = rotateLeft(ar + (br ^ cr ^ dr) + x[3], 14); 335 dl = rotateLeft(dl + ((al & cl) | (bl & ~(cl))) + x[8] + 0x8f1bbcdc, 15); 336 dr = rotateLeft(dr + (ar ^ br ^ cr) + x[11], 14); 337 cl = rotateLeft(cl + ((dl & bl) | (al & ~(bl))) + x[12] + 0x8f1bbcdc, 9); 338 cr = rotateLeft(cr + (dr ^ ar ^ br) + x[15], 6); 339 bl = rotateLeft(bl + ((cl & al) | (dl & ~(al))) + x[4] + 0x8f1bbcdc, 8); 340 br = rotateLeft(br + (cr ^ dr ^ ar) + x[0], 14); 341 al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[13] + 0x8f1bbcdc, 9); 342 ar = rotateLeft(ar + (br ^ cr ^ dr) + x[5], 6); 343 dl = rotateLeft(dl + ((al & cl) | (bl & ~(cl))) + x[3] + 0x8f1bbcdc, 14); 344 dr = rotateLeft(dr + (ar ^ br ^ cr) + x[12], 9); 345 cl = rotateLeft(cl + ((dl & bl) | (al & ~(bl))) + x[7] + 0x8f1bbcdc, 5); 346 cr = rotateLeft(cr + (dr ^ ar ^ br) + x[2], 12); 347 bl = rotateLeft(bl + ((cl & al) | (dl & ~(al))) + x[15] + 0x8f1bbcdc, 6); 348 br = rotateLeft(br + (cr ^ dr ^ ar) + x[13], 9); 349 al = rotateLeft(al + ((bl & dl) | (cl & ~(dl))) + x[14] + 0x8f1bbcdc, 8); 350 ar = rotateLeft(ar + (br ^ cr ^ dr) + x[9], 12); 351 dl = rotateLeft(dl + ((al & cl) | (bl & ~(cl))) + x[5] + 0x8f1bbcdc, 6); 352 dr = rotateLeft(dr + (ar ^ br ^ cr) + x[7], 5); 353 cl = rotateLeft(cl + ((dl & bl) | (al & ~(bl))) + x[6] + 0x8f1bbcdc, 5); 354 cr = rotateLeft(cr + (dr ^ ar ^ br) + x[10], 15); 355 bl = rotateLeft(bl + ((cl & al) | (dl & ~(al))) + x[2] + 0x8f1bbcdc, 12); 356 br = rotateLeft(br + (cr ^ dr ^ ar) + x[14], 8); 357 358 // Do not swap dl and dr; simply add the right value to context 359 360 context[0] += al; 361 context[1] += bl; 362 context[2] += cl; 363 context[3] += dr; 364 context[4] += ar; 365 context[5] += br; 366 context[6] += cr; 367 context[7] += dl; 368 369 x[] = 0; 370 } 371 372 } 373 374 /******************************************************************************* 375 376 *******************************************************************************/ 377 378 unittest 379 { 380 static istring[] strings = 381 [ 382 "", 383 "a", 384 "abc", 385 "message digest", 386 "abcdefghijklmnopqrstuvwxyz", 387 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 388 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 389 "12345678901234567890123456789012345678901234567890123456789012345678901234567890" 390 ]; 391 392 static istring[] results = 393 [ 394 "02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d", 395 "f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925", 396 "afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65", 397 "87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e", 398 "649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133", 399 "3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f", 400 "5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8", 401 "06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd" 402 ]; 403 404 Ripemd256 h = new Ripemd256(); 405 406 foreach (i, s; strings) 407 { 408 h.update(cast(ubyte[]) s); 409 char[] d = h.hexDigest; 410 411 test(d == results[i],":("~s~")("~d~")!=("~results[i]~")"); 412 } 413 414 char[] s = new char[1000000]; 415 for (auto i = 0; i < s.length; i++) s[i] = 'a'; 416 auto result = "ac953744e10e31514c150d4d8d7b677342e33399788296e43ae4850ce4f97978"; 417 h.update(cast(ubyte[]) s); 418 auto d = h.hexDigest; 419 420 test(d == result,":(1 million times \"a\")("~d~")!=("~result~")"); 421 }