001 package railo.commons.lang; 002 003 import java.io.File; 004 import java.io.FileInputStream; 005 import java.io.IOException; 006 import java.io.InputStream; 007 import java.io.UnsupportedEncodingException; 008 009 import railo.commons.io.IOUtil; 010 import railo.commons.io.res.Resource; 011 012 public final class MD5Hash { 013 014 /** 015 * Class constructor 016 * 017 */ 018 public MD5Hash () { 019 reset(); 020 } 021 022 /** 023 * Gets this hash sum as an array of 16 bytes. 024 * 025 * @return Array of 16 bytes, the hash of all updated bytes. 026 * 027 */ 028 public byte[] getHash() { 029 if (!finalState.valid) { 030 finalState.copy(workingState); 031 long bitCount = finalState.bitCount; 032 // Compute the number of left over bits 033 int leftOver = (int) (((bitCount >>> 3)) & 0x3f); 034 // Compute the amount of padding to add based on number of left over bits. 035 int padlen = (leftOver < 56) ? (56 - leftOver) : (120 - leftOver); 036 // add the padding 037 update(finalState, padding, 0, padlen); 038 // add the length (computed before padding was added) 039 update(finalState, encode(bitCount), 0, 8); 040 finalState.valid = true; 041 } 042 // make a copy of the hash before returning it. 043 return encode(finalState.state, 16); 044 } 045 046 /** 047 * Returns 32-character hex representation of this hash. 048 * 049 * @return String representation of this object's hash. 050 * 051 * 052 */ 053 public String getHashString(){ 054 return toHex(this.getHash()); 055 } 056 057 /** 058 * Gets the MD5 hash of the given byte array. 059 * 060 * @param b byte array for which an MD5 hash is desired. 061 * @return Array of 16 bytes, the hash of all updated bytes. 062 * 063 * 064 */ 065 public static byte[] getHash(byte[] b){ 066 MD5Hash md5 = new MD5Hash(); 067 md5.update(b); 068 return md5.getHash(); 069 } 070 071 /** 072 * Gets the MD5 hash of the given byte array. 073 * 074 * @param b byte array for which an MD5 hash is desired. 075 * @return 32-character hex representation the data's MD5 hash. 076 * 077 * 078 */ 079 public static String getHashString(byte[] b){ 080 MD5Hash md5 = new MD5Hash(); 081 md5.update(b); 082 return md5.getHashString(); 083 } 084 085 /** 086 * Gets the MD5 hash the data on the given InputStream. 087 * 088 * @param in byte array for which an MD5 hash is desired. 089 * @return Array of 16 bytes, the hash of all updated bytes. 090 * @throws IOException if an I/O error occurs. 091 * 092 * 093 */ 094 public static byte[] getHash(InputStream in) throws IOException { 095 MD5Hash md5 = new MD5Hash(); 096 byte[] buffer = new byte[1024]; 097 int read; 098 while ((read = in.read(buffer)) != -1){ 099 md5.update(buffer, read); 100 } 101 return md5.getHash(); 102 } 103 104 /** 105 * Gets the MD5 hash the data on the given InputStream. 106 * 107 * @param in byte array for which an MD5 hash is desired. 108 * @return 32-character hex representation the data's MD5 hash. 109 * @throws IOException if an I/O error occurs. 110 * 111 * 112 */ 113 public static String getHashString(InputStream in) throws IOException { 114 MD5Hash md5 = new MD5Hash(); 115 byte[] buffer = new byte[1024]; 116 int read; 117 while ((read = in.read(buffer)) != -1){ 118 md5.update(buffer, read); 119 } 120 return md5.getHashString(); 121 } 122 123 /** 124 * Gets the MD5 hash of the given file. 125 * 126 * @param f file for which an MD5 hash is desired. 127 * @return Array of 16 bytes, the hash of all updated bytes. 128 * @throws IOException if an I/O error occurs. 129 * 130 * 131 */ 132 public static byte[] getHash(File f) throws IOException { 133 InputStream is=null; 134 try { 135 return getHash(is=new FileInputStream(f)); 136 } 137 finally { 138 IOUtil.closeEL(is); 139 } 140 141 } 142 143 /** 144 * Gets the MD5 hash of the given file. 145 * 146 * @param f file for which an MD5 hash is desired. 147 * @return Array of 16 bytes, the hash of all updated bytes. 148 * @throws IOException if an I/O error occurs. 149 * 150 * 151 */ 152 public static byte[] getHash(Resource f) throws IOException { 153 InputStream is=null; 154 try { 155 return getHash(is=f.getInputStream()); 156 } 157 finally { 158 IOUtil.closeEL(is); 159 } 160 } 161 162 /** 163 * Gets the MD5 hash of the given file. 164 * 165 * @param f file array for which an MD5 hash is desired. 166 * @return 32-character hex representation the data's MD5 hash. 167 * @throws IOException if an I/O error occurs. 168 * 169 * 170 */ 171 public static String getHashString(File f) throws IOException { 172 InputStream is=null; 173 try { 174 return getHashString(is=new FileInputStream(f)); 175 } 176 finally { 177 IOUtil.closeEL(is); 178 } 179 } 180 181 /** 182 * Gets the MD5 hash of the given file. 183 * 184 * @param f file array for which an MD5 hash is desired. 185 * @return 32-character hex representation the data's MD5 hash. 186 * @throws IOException if an I/O error occurs. 187 * 188 * 189 */ 190 public static String getHashString(Resource f) throws IOException { 191 InputStream is=null; 192 try { 193 return getHashString(is=f.getInputStream()); 194 } 195 finally { 196 IOUtil.closeEL(is); 197 } 198 } 199 200 /** 201 * Gets the MD5 hash of the given String. 202 * The string is converted to bytes using the current 203 * platform's default character encoding. 204 * 205 * @param s String for which an MD5 hash is desired. 206 * @return Array of 16 bytes, the hash of all updated bytes. 207 * 208 * 209 */ 210 public static byte[] getHash(String s){ 211 MD5Hash md5 = new MD5Hash(); 212 md5.update(s); 213 return md5.getHash(); 214 } 215 216 /** 217 * Gets the MD5 hash of the given String. 218 * The string is converted to bytes using the current 219 * platform's default character encoding. 220 * 221 * @param s String for which an MD5 hash is desired. 222 * @return 32-character hex representation the data's MD5 hash. 223 * 224 * 225 */ 226 public static String getHashString(String s){ 227 MD5Hash md5 = new MD5Hash(); 228 md5.update(s); 229 return md5.getHashString(); 230 } 231 232 233 /** 234 * Gets the MD5 hash of the given String. 235 * 236 * @param s String for which an MD5 hash is desired. 237 * @param enc The name of a supported character encoding. 238 * @return Array of 16 bytes, the hash of all updated bytes. 239 * @throws UnsupportedEncodingException If the named encoding is not supported. 240 * 241 * 242 */ 243 public static byte[] getHash(String s, String enc) throws UnsupportedEncodingException { 244 MD5Hash md5 = new MD5Hash(); 245 md5.update(s, enc); 246 return md5.getHash(); 247 } 248 249 /** 250 * Gets the MD5 hash of the given String. 251 * 252 * @param s String for which an MD5 hash is desired. 253 * @param enc The name of a supported character encoding. 254 * @return 32-character hex representation the data's MD5 hash. 255 * @throws UnsupportedEncodingException If the named encoding is not supported. 256 * 257 * 258 */ 259 public static String getHashString(String s, String enc) throws UnsupportedEncodingException { 260 MD5Hash md5 = new MD5Hash(); 261 md5.update(s, enc); 262 return md5.getHashString(); 263 } 264 265 266 /** 267 * Reset the MD5 sum to its initial state. 268 * 269 * 270 */ 271 public void reset() { 272 workingState.reset(); 273 finalState.valid = false; 274 } 275 276 /** 277 * Returns 32-character hex representation of this hash. 278 * 279 * @return String representation of this object's hash. 280 * 281 * 282 */ 283 public String toString(){ 284 return getHashString(); 285 } 286 287 /** 288 * Update this hash with the given data. 289 * <p> 290 * A state may be passed into this method so that we can add padding 291 * and finalize a md5 hash without limiting our ability to update 292 * more data later. 293 * <p> 294 * If length bytes are not available to be hashed, as many bytes as 295 * possible will be hashed. 296 * 297 * @param state Which state is updated. 298 * @param buffer Array of bytes to be hashed. 299 * @param offset Offset to buffer array. 300 * @param length number of bytes to hash. 301 * 302 * 303 */ 304 private void update (MD5State state, byte buffer[], int offset, int length) { 305 306 finalState.valid = false; 307 308 // if length goes beyond the end of the buffer, cut it short. 309 if ((length + offset) > buffer.length){ 310 length = buffer.length - offset; 311 } 312 313 // compute number of bytes mod 64 314 // this is what we have sitting in a buffer 315 // that have not been hashed yet 316 int index = (int) (state.bitCount >>> 3) & 0x3f; 317 318 // add the length to the count (translate bytes to bits) 319 state.bitCount += length << 3; 320 321 int partlen = 64 - index; 322 323 int i = 0; 324 if (length >= partlen) { 325 System.arraycopy(buffer, offset, state.buffer, index, partlen); 326 transform(state, decode(state.buffer, 64, 0)); 327 for (i = partlen; (i + 63) < length; i+= 64){ 328 transform(state, decode(buffer, 64, i)); 329 } 330 index = 0; 331 } 332 333 // buffer remaining input 334 if (i < length) { 335 for (int start = i; i < length; i++) { 336 state.buffer[index + i - start] = buffer[i + offset]; 337 } 338 } 339 } 340 341 /** 342 * Update this hash with the given data. 343 * <p> 344 * If length bytes are not available to be hashed, as many bytes as 345 * possible will be hashed. 346 * 347 * @param buffer Array of bytes to be hashed. 348 * @param offset Offset to buffer array. 349 * @param length number of bytes to hash. 350 * 351 * 352 */ 353 public void update (byte buffer[], int offset, int length) { 354 update(workingState, buffer, offset, length); 355 } 356 357 /** 358 * Update this hash with the given data. 359 * <p> 360 * If length bytes are not available to be hashed, as many bytes as 361 * possible will be hashed. 362 * 363 * @param buffer Array of bytes to be hashed. 364 * @param length number of bytes to hash. 365 * 366 * 367 */ 368 public void update (byte buffer[], int length) { 369 update(buffer, 0, length); 370 } 371 372 /** 373 * Update this hash with the given data. 374 * 375 * @param buffer Array of bytes to be hashed. 376 * 377 * 378 */ 379 public void update (byte buffer[]) { 380 update(buffer, 0, buffer.length); 381 } 382 383 /** 384 * Updates this hash with a single byte. 385 * 386 * @param b byte to be hashed. 387 * 388 * 389 */ 390 public void update (byte b) { 391 byte buffer[] = new byte[1]; 392 buffer[0] = b; 393 update(buffer, 1); 394 } 395 396 /* * 397 * Update this hash with a long. 398 * This hash will be updated in a little endian order with the 399 * the least significan't byte going first. 400 * 401 * @param l long to be hashed. 402 * 403 * 404 * / 405 private void update (MD5State state, long l) { 406 update( 407 state, 408 new byte[] { 409 (byte)((l >>> 0) & 0xff), 410 (byte)((l >>> 8) & 0xff), 411 (byte)((l >>> 16) & 0xff), 412 (byte)((l >>> 24) & 0xff), 413 (byte)((l >>> 32) & 0xff), 414 (byte)((l >>> 40) & 0xff), 415 (byte)((l >>> 48) & 0xff), 416 (byte)((l >>> 56) & 0xff), 417 }, 418 0, 419 8 420 ); 421 }*/ 422 423 /** 424 * Update this hash with a String. 425 * The string is converted to bytes using the current 426 * platform's default character encoding. 427 * 428 * @param s String to be hashed. 429 * 430 * 431 */ 432 public void update (String s) { 433 update(s.getBytes()); 434 } 435 436 /** 437 * Update this hash with a String. 438 * 439 * @param s String to be hashed. 440 * @param enc The name of a supported character encoding. 441 * @throws UnsupportedEncodingException If the named encoding is not supported. 442 * 443 * 444 */ 445 public void update (String s, String enc) throws UnsupportedEncodingException { 446 update(s.getBytes(enc)); 447 } 448 449 /** 450 * The current state from which the hash sum 451 * can be computed or updated. 452 * 453 * 454 */ 455 private MD5State workingState = new MD5State(); 456 457 /** 458 * Cached copy of the final MD5 hash sum. This is created when 459 * the hash is requested and it is invalidated when the hash 460 * is updated. 461 * 462 * 463 */ 464 private MD5State finalState = new MD5State(); 465 466 /** 467 * Temporary buffer cached here for performance reasons. 468 * 469 * 470 */ 471 private int[] decodeBuffer = new int[16]; 472 473 /** 474 * 64 bytes of padding that can be added if the length 475 * is not divisible by 64. 476 * 477 * 478 */ 479 private static final byte padding[] = { 480 (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 481 0, 0, 0, 0, 0, 0, 0, 0, 482 0, 0, 0, 0, 0, 0, 0, 0, 483 0, 0, 0, 0, 0, 0, 0, 0, 484 0, 0, 0, 0, 0, 0, 0, 0, 485 0, 0, 0, 0, 0, 0, 0, 0, 486 0, 0, 0, 0, 0, 0, 0, 0, 487 0, 0, 0, 0, 0, 0, 0, 0, 488 }; 489 490 /** 491 * Contains internal state of the MD5 class. 492 * Passes MD5 test suite as defined in RFC1321. 493 * 494 * 495 */ 496 private class MD5State { 497 498 /** 499 * True if this state is valid. 500 * 501 * 502 */ 503 public boolean valid = true; 504 505 /** 506 * Reset to initial state. 507 * 508 * 509 */ 510 public void reset(){ 511 state[0] = 0x67452301; 512 state[1] = 0xefcdab89; 513 state[2] = 0x98badcfe; 514 state[3] = 0x10325476; 515 516 bitCount = 0; 517 } 518 519 /** 520 * 128-byte state 521 * 522 * 523 */ 524 public int state[] = new int[4]; 525 526 /** 527 * 64-bit count of the number of bits that have been hashed. 528 * 529 * 530 */ 531 public long bitCount; 532 533 /** 534 * 64-byte buffer (512 bits) for storing to-be-hashed characters 535 * 536 * 537 */ 538 public byte buffer[] = new byte[64]; 539 540 /** 541 * 542 */ 543 public MD5State() { 544 reset(); 545 } 546 547 /** 548 * Set this state to be exactly the same as some other. 549 * 550 * @param from state to copy from. 551 * 552 * 553 */ 554 public void copy(MD5State from) { 555 System.arraycopy(from.buffer, 0, this.buffer, 0, this.buffer.length); 556 System.arraycopy(from.state, 0, this.state, 0, this.state.length); 557 this.valid = from.valid; 558 this.bitCount = from.bitCount; 559 } 560 561 public String toString(){ 562 return state[0] + " " + state[1] + " " + state[2] + " " + state[3]; 563 } 564 } 565 566 567 /** 568 * Turns array of bytes into string representing each byte as 569 * a two digit unsigned hex number. 570 * 571 * @param hash Array of bytes to convert to hex-string 572 * @return Generated hex string 573 * 574 * 575 */ 576 private String toHex(byte hash[]) { 577 char[] chars = new char[2*hash.length]; 578 int h; 579 int l; 580 int count=0; 581 for (int i = 0 ; i < hash.length; i++) { 582 h = (hash[i] & 0xf0) >> 4 ; 583 l = (hash[i] & 0x0f) ; 584 chars[count++]= ((char)((h>9) ? 'a'+h-10 : '0'+h)); 585 chars[count++]= ((char)((l>9) ? 'a'+l-10 : '0'+l)); 586 } 587 return new String(chars) ; 588 } 589 590 591 592 private static int FF (int a, int b, int c, int d, int x, int s, int ac) { 593 a += ((b & c) | (~b & d)); 594 a += x; 595 a += ac; 596 //return rotateLeft(a, s) + b; 597 a = (a << s) | (a >>> (32 - s)); 598 return a + b; 599 } 600 601 private static int GG (int a, int b, int c, int d, int x, int s, int ac) { 602 a += ((b & d) | (c & ~d)); 603 a += x; 604 a += ac; 605 //return rotateLeft(a, s) + b; 606 a = (a << s) | (a >>> (32 - s)); 607 return a + b; 608 } 609 610 private static int HH (int a, int b, int c, int d, int x, int s, int ac) { 611 a += (b ^ c ^ d); 612 a += x; 613 a += ac; 614 //return rotateLeft(a, s) + b; 615 a = (a << s) | (a >>> (32 - s)); 616 return a + b; 617 } 618 619 private static int II (int a, int b, int c, int d, int x, int s, int ac) { 620 a += (c ^ (b | ~d)); 621 a += x; 622 a += ac; 623 //return rotateLeft(a, s) + b; 624 a = (a << s) | (a >>> (32 - s)); 625 return a + b; 626 } 627 628 private static byte[] encode(long l){ 629 byte[] out = new byte[8]; 630 out[0] = (byte) (l & 0xff); 631 out[1] = (byte) ((l >>> 8) & 0xff); 632 out[2] = (byte) ((l >>> 16) & 0xff); 633 out[3] = (byte) ((l >>> 24) & 0xff); 634 out[4] = (byte) ((l >>> 32) & 0xff); 635 out[5] = (byte) ((l >>> 40) & 0xff); 636 out[6] = (byte) ((l >>> 48) & 0xff); 637 out[7] = (byte) ((l >>> 56) & 0xff); 638 return out; 639 } 640 641 private static byte[] encode(int input[], int len){ 642 byte[] out = new byte[len]; 643 int i, j; 644 for (i = j = 0; j < len; i++, j += 4) { 645 out[j] = (byte) (input[i] & 0xff); 646 out[j + 1] = (byte) ((input[i] >>> 8) & 0xff); 647 out[j + 2] = (byte) ((input[i] >>> 16) & 0xff); 648 out[j + 3] = (byte) ((input[i] >>> 24) & 0xff); 649 } 650 return out; 651 } 652 653 private int[] decode(byte buffer[], int len, int offset){ 654 int i, j=offset; 655 for (i = 0; j < len; i++,j+=4) { 656 decodeBuffer[i] = (buffer[j] & 0xff) | 657 ((buffer[j+1] & 0xff) << 8) | 658 ((buffer[j+2] & 0xff) << 16) | 659 ((buffer[j+3] & 0xff) << 24 660 ); 661 } 662 return decodeBuffer; 663 } 664 665 private static void transform(MD5State state, int[] x){ 666 int a = state.state[0]; 667 int b = state.state[1]; 668 int c = state.state[2]; 669 int d = state.state[3]; 670 671 /* Round 1 */ 672 a = FF (a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */ 673 d = FF (d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */ 674 c = FF (c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */ 675 b = FF (b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */ 676 a = FF (a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */ 677 d = FF (d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */ 678 c = FF (c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */ 679 b = FF (b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */ 680 a = FF (a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */ 681 d = FF (d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */ 682 c = FF (c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */ 683 b = FF (b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */ 684 a = FF (a, b, c, d, x[12], 7, 0x6b901122); /* 13 */ 685 d = FF (d, a, b, c, x[13], 12, 0xfd987193); /* 14 */ 686 c = FF (c, d, a, b, x[14], 17, 0xa679438e); /* 15 */ 687 b = FF (b, c, d, a, x[15], 22, 0x49b40821); /* 16 */ 688 689 /* Round 2 */ 690 a = GG (a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */ 691 d = GG (d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */ 692 c = GG (c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */ 693 b = GG (b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */ 694 a = GG (a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */ 695 d = GG (d, a, b, c, x[10], 9, 0x02441453); /* 22 */ 696 c = GG (c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */ 697 b = GG (b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */ 698 a = GG (a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */ 699 d = GG (d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */ 700 c = GG (c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */ 701 b = GG (b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */ 702 a = GG (a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */ 703 d = GG (d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */ 704 c = GG (c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */ 705 b = GG (b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */ 706 707 /* Round 3 */ 708 a = HH (a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */ 709 d = HH (d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */ 710 c = HH (c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */ 711 b = HH (b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */ 712 a = HH (a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */ 713 d = HH (d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */ 714 c = HH (c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */ 715 b = HH (b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */ 716 a = HH (a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */ 717 d = HH (d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */ 718 c = HH (c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */ 719 b = HH (b, c, d, a, x[ 6], 23, 0x04881d05); /* 44 */ 720 a = HH (a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */ 721 d = HH (d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */ 722 c = HH (c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */ 723 b = HH (b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */ 724 725 /* Round 4 */ 726 a = II (a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */ 727 d = II (d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */ 728 c = II (c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */ 729 b = II (b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */ 730 a = II (a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */ 731 d = II (d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */ 732 c = II (c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */ 733 b = II (b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */ 734 a = II (a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */ 735 d = II (d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */ 736 c = II (c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */ 737 b = II (b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */ 738 a = II (a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */ 739 d = II (d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */ 740 c = II (c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */ 741 b = II (b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */ 742 743 state.state[0] += a; 744 state.state[1] += b; 745 state.state[2] += c; 746 state.state[3] += d; 747 } 748 }