KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > claros > chat > utility > MD5


1 /*
2  * MD5 implementation
3  * written Santeri Paavolainen, Helsinki Finland 1996
4  * (c) Santeri Paavolainen, Helsinki Finland 1996
5  * modifications Copyright (C) 2002-2004 Stephen Ostermiller
6  * http://ostermiller.org/contact.pl?regarding=Java+Utilities
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * See COPYING.TXT for details.
19  *
20  * The original work by Santeri Paavolainen can be found at
21  * http://www.helsinki.fi/~sjpaavol/programs/md5/
22  *
23  * This Java class has been derived from the RSA Data Security, Inc. MD5
24  * Message-Digest Algorithm and its reference implementation.
25  */

26 package org.claros.chat.utility;
27
28 import java.io.*;
29
30 /**
31  * MD5 hash generator.
32  * More information about this class is available from <a target="_top" HREF=
33  * "http://ostermiller.org/utils/MD5.html">ostermiller.org</a>.
34  * <p>
35  * This class takes as input a message of arbitrary length and produces
36  * as output a 128-bit "fingerprint" or "message digest" of the input.
37  * It is conjectured that it is computationally infeasible to produce
38  * two messages having the same message digest, or to produce any
39  * message having a given pre-specified target message digest. The MD5
40  * algorithm is intended for digital signature applications, where a
41  * large file must be "compressed" in a secure manner before being
42  * encrypted with a private (secret) key under a public-key cryptosystem
43  * such as RSA.
44  * <p>
45  * For more information see RFC1321.
46  *
47  * @see MD5OutputStream
48  * @see MD5InputStream
49  *
50  * @author Santeri Paavolainen http://www.helsinki.fi/~sjpaavol/programs/md5/
51  * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
52  * @since ostermillerutils 1.00.00
53  */

54 public class MD5 {
55
56     /**
57      * Class constructor
58      *
59      * @since ostermillerutils 1.00.00
60      */

61     public MD5 () {
62         reset();
63     }
64
65     /**
66      * Command line program that will take files as arguments
67      * and output the MD5 sum for each file.
68      *
69      * @param args command line arguments
70      *
71      * @since ostermillerutils 1.00.00
72      */

73     public static void main (String JavaDoc[] args){
74         if (args.length == 0){
75             System.err.println("Please specify a file.");
76         } else {
77             for (int i=0; i<args.length; i++){
78                 try {
79                     System.out.println(MD5.getHashString(new File(args[i])) + " " + args[i]);
80                 } catch (IOException x){
81                     System.err.println(x.getMessage());
82                 }
83             }
84         }
85     }
86
87     /**
88      * Gets this hash sum as an array of 16 bytes.
89      *
90      * @return Array of 16 bytes, the hash of all updated bytes.
91      *
92      * @since ostermillerutils 1.00.00
93      */

94     public byte[] getHash() {
95         if (!finalState.valid) {
96             finalState.copy(workingState);
97             long bitCount = finalState.bitCount;
98             // Compute the number of left over bits
99
int leftOver = (int) (((bitCount >>> 3)) & 0x3f);
100             // Compute the amount of padding to add based on number of left over bits.
101
int padlen = (leftOver < 56) ? (56 - leftOver) : (120 - leftOver);
102             // add the padding
103
update(finalState, padding, 0, padlen);
104             // add the length (computed before padding was added)
105
update(finalState, encode(bitCount), 0, 8);
106             finalState.valid = true;
107         }
108         // make a copy of the hash before returning it.
109
return encode(finalState.state, 16);
110     }
111
112     /**
113      * Returns 32-character hex representation of this hash.
114      *
115      * @return String representation of this object's hash.
116      *
117      * @since ostermillerutils 1.00.00
118      */

119     public String JavaDoc getHashString(){
120         return toHex(this.getHash());
121     }
122
123     /**
124      * Gets the MD5 hash of the given byte array.
125      *
126      * @param b byte array for which an MD5 hash is desired.
127      * @return Array of 16 bytes, the hash of all updated bytes.
128      *
129      * @since ostermillerutils 1.00.00
130      */

131     public static byte[] getHash(byte[] b){
132         MD5 md5 = new MD5();
133         md5.update(b);
134         return md5.getHash();
135     }
136
137     /**
138      * Gets the MD5 hash of the given byte array.
139      *
140      * @param b byte array for which an MD5 hash is desired.
141      * @return 32-character hex representation the data's MD5 hash.
142      *
143      * @since ostermillerutils 1.00.00
144      */

145     public static String JavaDoc getHashString(byte[] b){
146         MD5 md5 = new MD5();
147         md5.update(b);
148         return md5.getHashString();
149     }
150
151     /**
152      * Gets the MD5 hash the data on the given InputStream.
153      *
154      * @param in byte array for which an MD5 hash is desired.
155      * @return Array of 16 bytes, the hash of all updated bytes.
156      * @throws IOException if an I/O error occurs.
157      *
158      * @since ostermillerutils 1.00.00
159      */

160     public static byte[] getHash(InputStream in) throws IOException {
161         MD5 md5 = new MD5();
162         byte[] buffer = new byte[1024];
163         int read;
164         while ((read = in.read(buffer)) != -1){
165             md5.update(buffer, read);
166         }
167         return md5.getHash();
168     }
169
170     /**
171      * Gets the MD5 hash the data on the given InputStream.
172      *
173      * @param in byte array for which an MD5 hash is desired.
174      * @return 32-character hex representation the data's MD5 hash.
175      * @throws IOException if an I/O error occurs.
176      *
177      * @since ostermillerutils 1.00.00
178      */

179     public static String JavaDoc getHashString(InputStream in) throws IOException {
180         MD5 md5 = new MD5();
181         byte[] buffer = new byte[1024];
182         int read;
183         while ((read = in.read(buffer)) != -1){
184             md5.update(buffer, read);
185         }
186         return md5.getHashString();
187     }
188
189     /**
190      * Gets the MD5 hash of the given file.
191      *
192      * @param f file for which an MD5 hash is desired.
193      * @return Array of 16 bytes, the hash of all updated bytes.
194      * @throws IOException if an I/O error occurs.
195      *
196      * @since ostermillerutils 1.00.00
197      */

198     public static byte[] getHash(File f) throws IOException {
199         return getHash(new FileInputStream(f));
200     }
201
202     /**
203      * Gets the MD5 hash of the given file.
204      *
205      * @param f file array for which an MD5 hash is desired.
206      * @return 32-character hex representation the data's MD5 hash.
207      * @throws IOException if an I/O error occurs.
208      *
209      * @since ostermillerutils 1.00.00
210      */

211     public static String JavaDoc getHashString(File f) throws IOException {
212         return getHashString(new FileInputStream(f));
213     }
214
215     /**
216      * Gets the MD5 hash of the given String.
217      * The string is converted to bytes using the current
218      * platform's default character encoding.
219      *
220      * @param s String for which an MD5 hash is desired.
221      * @return Array of 16 bytes, the hash of all updated bytes.
222      *
223      * @since ostermillerutils 1.00.00
224      */

225     public static byte[] getHash(String JavaDoc s){
226         MD5 md5 = new MD5();
227         md5.update(s);
228         return md5.getHash();
229     }
230
231     /**
232      * Gets the MD5 hash of the given String.
233      * The string is converted to bytes using the current
234      * platform's default character encoding.
235      *
236      * @param s String for which an MD5 hash is desired.
237      * @return 32-character hex representation the data's MD5 hash.
238      *
239      * @since ostermillerutils 1.00.00
240      */

241     public static String JavaDoc getHashString(String JavaDoc s){
242         MD5 md5 = new MD5();
243         md5.update(s);
244         return md5.getHashString();
245     }
246
247
248     /**
249      * Gets the MD5 hash of the given String.
250      *
251      * @param s String for which an MD5 hash is desired.
252      * @param enc The name of a supported character encoding.
253      * @return Array of 16 bytes, the hash of all updated bytes.
254      * @throws UnsupportedEncodingException If the named encoding is not supported.
255      *
256      * @since ostermillerutils 1.00.00
257      */

258     public static byte[] getHash(String JavaDoc s, String JavaDoc enc) throws UnsupportedEncodingException {
259         MD5 md5 = new MD5();
260         md5.update(s, enc);
261         return md5.getHash();
262     }
263
264     /**
265      * Gets the MD5 hash of the given String.
266      *
267      * @param s String for which an MD5 hash is desired.
268      * @param enc The name of a supported character encoding.
269      * @return 32-character hex representation the data's MD5 hash.
270      * @throws UnsupportedEncodingException If the named encoding is not supported.
271      *
272      * @since ostermillerutils 1.00.00
273      */

274     public static String JavaDoc getHashString(String JavaDoc s, String JavaDoc enc) throws UnsupportedEncodingException {
275         MD5 md5 = new MD5();
276         md5.update(s, enc);
277         return md5.getHashString();
278     }
279
280
281     /**
282      * Reset the MD5 sum to its initial state.
283      *
284      * @since ostermillerutils 1.00.00
285      */

286     public void reset() {
287         workingState.reset();
288         finalState.valid = false;
289     }
290
291     /**
292      * Returns 32-character hex representation of this hash.
293      *
294      * @return String representation of this object's hash.
295      *
296      * @since ostermillerutils 1.00.00
297      */

298     public String JavaDoc toString(){
299         return getHashString();
300     }
301
302     /**
303      * Update this hash with the given data.
304      * <p>
305      * A state may be passed into this method so that we can add padding
306      * and finalize a md5 hash without limiting our ability to update
307      * more data later.
308      * <p>
309      * If length bytes are not available to be hashed, as many bytes as
310      * possible will be hashed.
311      *
312      * @param state Which state is updated.
313      * @param buffer Array of bytes to be hashed.
314      * @param offset Offset to buffer array.
315      * @param length number of bytes to hash.
316      *
317      * @since ostermillerutils 1.00.00
318      */

319     private void update (MD5State state, byte buffer[], int offset, int length) {
320
321         finalState.valid = false;
322
323         // if length goes beyond the end of the buffer, cut it short.
324
if ((length + offset) > buffer.length){
325             length = buffer.length - offset;
326         }
327
328         // compute number of bytes mod 64
329
// this is what we have sitting in a buffer
330
// that have not been hashed yet
331
int index = (int) (state.bitCount >>> 3) & 0x3f;
332
333         // add the length to the count (translate bytes to bits)
334
state.bitCount += length << 3;
335
336         int partlen = 64 - index;
337
338         int i = 0;
339         if (length >= partlen) {
340             System.arraycopy(buffer, offset, state.buffer, index, partlen);
341             transform(state, decode(state.buffer, 64, 0));
342             for (i = partlen; (i + 63) < length; i+= 64){
343                 transform(state, decode(buffer, 64, i));
344             }
345             index = 0;
346         }
347
348         // buffer remaining input
349
if (i < length) {
350             for (int start = i; i < length; i++) {
351                 state.buffer[index + i - start] = buffer[i + offset];
352             }
353         }
354     }
355
356     /**
357      * Update this hash with the given data.
358      * <p>
359      * If length bytes are not available to be hashed, as many bytes as
360      * possible will be hashed.
361      *
362      * @param buffer Array of bytes to be hashed.
363      * @param offset Offset to buffer array.
364      * @param length number of bytes to hash.
365      *
366      * @since ostermillerutils 1.00.00
367      */

368     public void update (byte buffer[], int offset, int length) {
369         update(workingState, buffer, offset, length);
370     }
371
372     /**
373      * Update this hash with the given data.
374      * <p>
375      * If length bytes are not available to be hashed, as many bytes as
376      * possible will be hashed.
377      *
378      * @param buffer Array of bytes to be hashed.
379      * @param length number of bytes to hash.
380      *
381      * @since ostermillerutils 1.00.00
382      */

383     public void update (byte buffer[], int length) {
384         update(buffer, 0, length);
385     }
386
387     /**
388      * Update this hash with the given data.
389      *
390      * @param buffer Array of bytes to be hashed.
391      *
392      * @since ostermillerutils 1.00.00
393      */

394     public void update (byte buffer[]) {
395         update(buffer, 0, buffer.length);
396     }
397
398     /**
399      * Updates this hash with a single byte.
400      *
401      * @param b byte to be hashed.
402      *
403      * @since ostermillerutils 1.00.00
404      */

405     public void update (byte b) {
406         byte buffer[] = new byte[1];
407         buffer[0] = b;
408         update(buffer, 1);
409     }
410
411     /**
412      * Update this hash with a long.
413      * This hash will be updated in a little endian order with the
414      * the least significant byte going first.
415      *
416      * @param l long to be hashed.
417      *
418      * @since ostermillerutils 1.00.00
419      */

420     /*
421     private void update (MD5State state, long l) {
422         update(
423             state,
424             new byte[] {
425                 (byte)((l >>> 0) & 0xff),
426                 (byte)((l >>> 8) & 0xff),
427                 (byte)((l >>> 16) & 0xff),
428                 (byte)((l >>> 24) & 0xff),
429                 (byte)((l >>> 32) & 0xff),
430                 (byte)((l >>> 40) & 0xff),
431                 (byte)((l >>> 48) & 0xff),
432                 (byte)((l >>> 56) & 0xff),
433             },
434             0,
435             8
436         );
437     }
438     */

439
440     /**
441      * Update this hash with a String.
442      * The string is converted to bytes using the current
443      * platform's default character encoding.
444      *
445      * @param s String to be hashed.
446      *
447      * @since ostermillerutils 1.00.00
448      */

449     public void update (String JavaDoc s) {
450         update(s.getBytes());
451     }
452
453     /**
454      * Update this hash with a String.
455      *
456      * @param s String to be hashed.
457      * @param enc The name of a supported character encoding.
458      * @throws UnsupportedEncodingException If the named encoding is not supported.
459      *
460      * @since ostermillerutils 1.00.00
461      */

462     public void update (String JavaDoc s, String JavaDoc enc) throws UnsupportedEncodingException {
463         update(s.getBytes(enc));
464     }
465
466     /**
467      * The current state from which the hash sum
468      * can be computed or updated.
469      *
470      * @since ostermillerutils 1.00.00
471      */

472     private MD5State workingState = new MD5State();
473
474     /**
475      * Cached copy of the final MD5 hash sum. This is created when
476      * the hash is requested and it is invalidated when the hash
477      * is updated.
478      *
479      * @since ostermillerutils 1.00.00
480      */

481     private MD5State finalState = new MD5State();
482
483     /**
484      * Temporary buffer cached here for performance reasons.
485      *
486      * @since ostermillerutils 1.00.00
487      */

488     private int[] decodeBuffer = new int[16];
489
490     /**
491      * 64 bytes of padding that can be added if the length
492      * is not divisible by 64.
493      *
494      * @since ostermillerutils 1.00.00
495      */

496     private static final byte padding[] = {
497         (byte) 0x80, 0, 0, 0, 0, 0, 0, 0,
498                 0, 0, 0, 0, 0, 0, 0, 0,
499                 0, 0, 0, 0, 0, 0, 0, 0,
500                 0, 0, 0, 0, 0, 0, 0, 0,
501                 0, 0, 0, 0, 0, 0, 0, 0,
502                 0, 0, 0, 0, 0, 0, 0, 0,
503                 0, 0, 0, 0, 0, 0, 0, 0,
504                 0, 0, 0, 0, 0, 0, 0, 0,
505     };
506
507     /**
508      * Contains internal state of the MD5 class.
509      * Passes MD5 test suite as defined in RFC1321.
510      *
511      * @since ostermillerutils 1.00.00
512      */

513     private class MD5State {
514
515         /**
516          * True if this state is valid.
517          *
518          * @since ostermillerutils 1.00.00
519          */

520         public boolean valid = true;
521
522         /**
523          * Reset to initial state.
524          *
525          * @since ostermillerutils 1.00.00
526          */

527         public void reset(){
528             state[0] = 0x67452301;
529             state[1] = 0xefcdab89;
530             state[2] = 0x98badcfe;
531             state[3] = 0x10325476;
532
533             bitCount = 0;
534         }
535
536         /**
537          * 128-byte state
538          *
539          * @since ostermillerutils 1.00.00
540          */

541         public int state[] = new int[4];
542
543         /**
544          * 64-bit count of the number of bits that have been hashed.
545          *
546          * @since ostermillerutils 1.00.00
547          */

548         public long bitCount;
549
550         /**
551          * 64-byte buffer (512 bits) for storing to-be-hashed characters
552          *
553          * @since ostermillerutils 1.00.00
554          */

555         public byte buffer[] = new byte[64];
556
557         public MD5State() {
558             reset();
559         }
560
561         /**
562          * Set this state to be exactly the same as some other.
563          *
564          * @param from state to copy from.
565          *
566          * @since ostermillerutils 1.00.00
567          */

568         public void copy(MD5State from) {
569             System.arraycopy(from.buffer, 0, this.buffer, 0, this.buffer.length);
570             System.arraycopy(from.state, 0, this.state, 0, this.state.length);
571             this.valid = from.valid;
572             this.bitCount = from.bitCount;
573         }
574
575         public String JavaDoc toString(){
576             return state[0] + " " + state[1] + " " + state[2] + " " + state[3];
577         }
578     }
579
580
581     /**
582      * Turns array of bytes into string representing each byte as
583      * a two digit unsigned hex number.
584      *
585      * @param hash Array of bytes to convert to hex-string
586      * @return Generated hex string
587      *
588      * @since ostermillerutils 1.00.00
589      */

590     private static String JavaDoc toHex(byte hash[]){
591         String JavaDoc buf = "";
592         for (int i=0; i<hash.length; i++){
593             int intVal = hash[i] & 0xff;
594             if (intVal < 0x10){
595                 // append a zero before a one digit hex
596
// number to make it two digits.
597
buf += "0";
598             }
599             buf += (Integer.toHexString(intVal));
600         }
601         return buf.toString();
602     }
603
604     private static int FF (int a, int b, int c, int d, int x, int s, int ac) {
605         a += ((b & c) | (~b & d));
606         a += x;
607         a += ac;
608         //return rotateLeft(a, s) + b;
609
a = (a << s) | (a >>> (32 - s));
610         return a + b;
611     }
612
613     private static int GG (int a, int b, int c, int d, int x, int s, int ac) {
614         a += ((b & d) | (c & ~d));
615         a += x;
616         a += ac;
617         //return rotateLeft(a, s) + b;
618
a = (a << s) | (a >>> (32 - s));
619         return a + b;
620     }
621
622     private static int HH (int a, int b, int c, int d, int x, int s, int ac) {
623         a += (b ^ c ^ d);
624         a += x;
625         a += ac;
626         //return rotateLeft(a, s) + b;
627
a = (a << s) | (a >>> (32 - s));
628         return a + b;
629     }
630
631     private static int II (int a, int b, int c, int d, int x, int s, int ac) {
632         a += (c ^ (b | ~d));
633         a += x;
634         a += ac;
635         //return rotateLeft(a, s) + b;
636
a = (a << s) | (a >>> (32 - s));
637         return a + b;
638     }
639
640     private static byte[] encode(long l){
641         byte[] out = new byte[8];
642         out[0] = (byte) (l & 0xff);
643         out[1] = (byte) ((l >>> 8) & 0xff);
644         out[2] = (byte) ((l >>> 16) & 0xff);
645         out[3] = (byte) ((l >>> 24) & 0xff);
646         out[4] = (byte) ((l >>> 32) & 0xff);
647         out[5] = (byte) ((l >>> 40) & 0xff);
648         out[6] = (byte) ((l >>> 48) & 0xff);
649         out[7] = (byte) ((l >>> 56) & 0xff);
650         return out;
651     }
652
653     private static byte[] encode(int input[], int len){
654         byte[] out = new byte[len];
655         int i, j;
656         for (i = j = 0; j < len; i++, j += 4) {
657             out[j] = (byte) (input[i] & 0xff);
658             out[j + 1] = (byte) ((input[i] >>> 8) & 0xff);
659             out[j + 2] = (byte) ((input[i] >>> 16) & 0xff);
660             out[j + 3] = (byte) ((input[i] >>> 24) & 0xff);
661         }
662         return out;
663     }
664
665     private int[] decode(byte buffer[], int len, int offset){
666         int i, j;
667         for (i = j = 0; j < len; i++, j += 4) {
668             decodeBuffer[i] = (
669                 (int) (buffer[j + offset] & 0xff)) |
670                 (((int) (buffer[j + 1 + offset] & 0xff)) << 8) |
671                 (((int) (buffer[j + 2 + offset] & 0xff)) << 16) |
672                 (((int) (buffer[j + 3 + offset] & 0xff)) << 24
673             );
674         }
675         return decodeBuffer;
676     }
677
678     private static void transform(MD5State state, int[] x){
679         int a = state.state[0];
680         int b = state.state[1];
681         int c = state.state[2];
682         int d = state.state[3];
683
684         /* Round 1 */
685         a = FF (a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */
686         d = FF (d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */
687         c = FF (c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */
688         b = FF (b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */
689         a = FF (a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */
690         d = FF (d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */
691         c = FF (c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */
692         b = FF (b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */
693         a = FF (a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */
694         d = FF (d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */
695         c = FF (c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
696         b = FF (b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
697         a = FF (a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
698         d = FF (d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
699         c = FF (c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
700         b = FF (b, c, d, a, x[15], 22, 0x49b40821); /* 16 */
701
702         /* Round 2 */
703         a = GG (a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */
704         d = GG (d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */
705         c = GG (c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
706         b = GG (b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */
707         a = GG (a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */
708         d = GG (d, a, b, c, x[10], 9, 0x02441453); /* 22 */
709         c = GG (c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
710         b = GG (b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */
711         a = GG (a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */
712         d = GG (d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
713         c = GG (c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */
714         b = GG (b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */
715         a = GG (a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
716         d = GG (d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */
717         c = GG (c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */
718         b = GG (b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */
719
720         /* Round 3 */
721         a = HH (a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */
722         d = HH (d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */
723         c = HH (c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
724         b = HH (b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
725         a = HH (a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */
726         d = HH (d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */
727         c = HH (c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */
728         b = HH (b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
729         a = HH (a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
730         d = HH (d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */
731         c = HH (c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */
732         b = HH (b, c, d, a, x[ 6], 23, 0x04881d05); /* 44 */
733         a = HH (a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */
734         d = HH (d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
735         c = HH (c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
736         b = HH (b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */
737
738         /* Round 4 */
739         a = II (a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */
740         d = II (d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */
741         c = II (c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
742         b = II (b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */
743         a = II (a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
744         d = II (d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */
745         c = II (c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
746         b = II (b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */
747         a = II (a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */
748         d = II (d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
749         c = II (c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */
750         b = II (b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
751         a = II (a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */
752         d = II (d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
753         c = II (c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */
754         b = II (b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */
755
756         state.state[0] += a;
757         state.state[1] += b;
758         state.state[2] += c;
759         state.state[3] += d;
760     }
761 }
Popular Tags