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