KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > Ostermiller > util > 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 com.Ostermiller.util;
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     private void update (MD5State state, long l) {
421         update(
422             state,
423             new byte[] {
424                 (byte)((l >>> 0) & 0xff),
425                 (byte)((l >>> 8) & 0xff),
426                 (byte)((l >>> 16) & 0xff),
427                 (byte)((l >>> 24) & 0xff),
428                 (byte)((l >>> 32) & 0xff),
429                 (byte)((l >>> 40) & 0xff),
430                 (byte)((l >>> 48) & 0xff),
431                 (byte)((l >>> 56) & 0xff),
432             },
433             0,
434             8
435         );
436     }
437
438     /**
439      * Update this hash with a String.
440      * The string is converted to bytes using the current
441      * platform's default character encoding.
442      *
443      * @param s String to be hashed.
444      *
445      * @since ostermillerutils 1.00.00
446      */

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

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

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

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

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

494     private static final byte padding[] = {
495         (byte) 0x80, 0, 0, 0, 0, 0, 0, 0,
496                 0, 0, 0, 0, 0, 0, 0, 0,
497                 0, 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     };
504
505     /**
506      * Contains internal state of the MD5 class.
507      * Passes MD5 test suite as defined in RFC1321.
508      *
509      * @since ostermillerutils 1.00.00
510      */

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

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

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

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

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

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

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

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