View Javadoc

1   package org.apache.java.security;
2   
3   /*
4    * Copyright 2001-2005 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License")
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  /***
20   * This class implements the Message Digest 5 algorithm (MD5) as
21   * defined in RFC-1321.
22   *
23   * <p><b>Note:</b> even if standard Java 1.1 APIs already provide a
24   * MD5 implementation, this class is used on those Java runtime
25   * environments (like Kaffe) where the package
26   * <code>java.security</code> is highly improbable to be found.
27   *
28   * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
29   * @version $Id: MD5.java 264148 2005-08-29 14:21:04Z henning $
30   * @deprecated Use the java.security package.
31   */
32  public final class MD5
33      extends MessageDigest
34  {
35      private long counter;
36      private int reminder;
37      private byte buffer[];
38      private int state[];
39      private int x[];
40  
41      /************************ MD5 Functions ***********************/
42  
43      // 16 * 4 bytes
44      static byte padding[] =
45      {
46          (byte) 0x80,
47          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
51      };
52  
53      /************************ Self Test ***********************/
54  
55      private static String[] messages =
56      {
57          "",
58          "a",
59          "abc",
60          "message digest",
61          "abcdefghijklmnopqrstuvwxyz",
62          "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
63          "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
64      };
65  
66      private static String[] digests =
67      {
68          "d41d8cd98f00b204e9800998ecf8427e",
69          "0cc175b9c0f1b6a831c399e269772661",
70          "900150983cd24fb0d6963f7d28e17f72",
71          "f96b697d7cb7938d525a2f31aaf161d0",
72          "c3fcd3d76192e4007dfb496cca67e13b",
73          "d174ab98d277d9f5a5611c2c9f419d9f",
74          "57edf4a22be3c955ac49da2e2107b67a",
75      };
76  
77  
78      /***
79       * Creates the algorithm and reset its state.
80       */
81      public MD5()
82      {
83          super();
84      }
85  
86      /***
87       * Append another block of specified length to the message
88       * starting at the given offset.
89       *
90       * @param block A byte[].
91       * @param offset An int.
92       * @param length An int.
93       */
94      public void append(byte[] block,
95                         int offset,
96                         int length)
97      {
98          while (true)
99          {
100             if (length >= reminder)
101             {
102                 System.arraycopy(block, offset, buffer,
103                                  (int) (counter & 63L), reminder);
104                 transform(buffer);
105                 counter += reminder;
106                 offset += reminder;
107                 length -= reminder;
108                 reminder = 64;
109             }
110             else
111             {
112                 System.arraycopy(block, offset, buffer,
113                                  (int) (counter & 63L), length);
114                 counter += length;
115                 reminder -= length;
116                 break;
117             }
118         }
119     }
120 
121     /************************ Byte/Int utilities ***********************/
122 
123     /***
124      * Converts a 64-byte array into a 16-int array.
125      *
126      * @param in A byte[].
127      * @param out An int[].
128      */
129     private static void byte2int(byte[] in,
130                                  int[] out)
131     {
132         for (int inpos = 0, outpos = 0; outpos < 16; outpos++)
133         {
134             out[outpos] = ((((int) (in[inpos++] & 0xff))) |
135                            (((int) (in[inpos++] & 0xff)) << 8) |
136                            (((int) (in[inpos++] & 0xff)) << 16) |
137                            (((int) (in[inpos++] & 0xff)) << 24));
138         }
139     }
140 
141     /***
142      * Appends a message block with specified length starting from the
143      * given offset, and return its message digest.
144      *
145      * @param block A byte[].
146      * @param offset An int.
147      * @param length An int.
148      */
149     public byte[] digest(byte[] block,
150                          int offset,
151                          int length)
152     {
153         this.append(block, offset, length);
154 
155         byte[] bits = toBytes(counter << 3);
156         byte[] digest = new byte[16];
157 
158         if (reminder > 8)
159         {
160             append(padding, 0, reminder - 8);
161         }
162         else
163         {
164             append(padding, 0, 64 + (reminder - 8));
165         }
166 
167         append(bits, 0, 8);
168 
169         int2byte(state, digest);
170 
171         this.reset();
172         return digest;
173     }
174 
175     /*
176      * Method F.
177      *
178      * @param x An int.
179      * @param y An int.
180      * @param z An int.
181      * @return An int.
182      */
183     static private int F(int x,
184                          int y,
185                          int z)
186     {
187         return (z ^ (x & (y^z)));
188     }
189 
190     /*
191      * Method FF.
192      *
193      * @param a An int.
194      * @param b An int.
195      * @param c An int.
196      * @param d An int.
197      * @param x An int.
198      * @param s An int.
199      * @param ac An int.
200      * @return An int.
201      */
202     static private int FF(int a,
203                           int b,
204                           int c,
205                           int d,
206                           int x,
207                           int s,
208                           int ac)
209     {
210         a += x + ac + F(b,c,d);
211         a = (a << s | a >>> -s);
212         return a + b;
213     }
214 
215     /*
216      * Method G.
217      *
218      * @param x An int.
219      * @param y An int.
220      * @param z An int.
221      * @return An int.
222      */
223     static private int G(int x,
224                          int y,
225                          int z)
226     {
227         return (y ^ (z & (x^y)));
228     }
229 
230     /*
231      * Method GG.
232      *
233      * @param a An int.
234      * @param b An int.
235      * @param c An int.
236      * @param d An int.
237      * @param x An int.
238      * @param s An int.
239      * @param ac An int.
240      * @return An int.
241      */
242     static private int GG(int a,
243                           int b,
244                           int c,
245                           int d,
246                           int x,
247                           int s,
248                           int ac)
249     {
250         a += x + ac + G(b,c,d);
251         a = (a << s | a >>> -s);
252         return a + b;
253     }
254 
255     /*
256      * Method H.
257      *
258      * @param x An int.
259      * @param y An int.
260      * @param z An int.
261      * @return An int.
262      */
263     static private int H(int x,
264                          int y,
265                          int z)
266     {
267         return (x ^ y ^ z);
268     }
269 
270     /*
271      * Method HH.
272      *
273      * @param a An int.
274      * @param b An int.
275      * @param c An int.
276      * @param d An int.
277      * @param x An int.
278      * @param s An int.
279      * @param ac An int.
280      * @return An int.
281      */
282     static private int HH(int a,
283                           int b,
284                           int c,
285                           int d,
286                           int x,
287                           int s,
288                           int ac)
289     {
290         a += x + ac + H(b,c,d);
291         a = (a << s | a >>> -s);
292         return a + b;
293     }
294 
295     /*
296      * Method I.
297      *
298      * @param x An int.
299      * @param y An int.
300      * @param z An int.
301      * @return An int.
302      */
303     static private int I(int x,
304                          int y,
305                          int z)
306     {
307         return (y ^ (x | ~z));
308     }
309 
310     /*
311      * Method II.
312      *
313      * @param a An int.
314      * @param b An int.
315      * @param c An int.
316      * @param d An int.
317      * @param x An int.
318      * @param s An int.
319      * @param ac An int.
320      * @return An int.
321      */
322     static private int II(int a,
323                           int b,
324                           int c,
325                           int d,
326                           int x,
327                           int s,
328                           int ac)
329     {
330         a += x + ac + I(b,c,d);
331         a = (a << s | a >>> -s);
332         return a + b;
333     }
334 
335     /***
336      * Converts a 4-int array into a 16-byte array.
337      *
338      * @param in An int[].
339      * @param out A byte[].
340      */
341     private static void int2byte(int[] in,
342                                  byte[] out)
343     {
344         for (int inpos = 0, outpos = 0; inpos < 4; inpos++)
345         {
346             out[outpos++] = (byte) (in[inpos] & 0xff);
347             out[outpos++] = (byte) ((in[inpos] >>> 8) & 0xff);
348             out[outpos++] = (byte) ((in[inpos] >>> 16) & 0xff);
349             out[outpos++] = (byte) ((in[inpos] >>> 24) & 0xff);
350         }
351     }
352 
353     /*
354      * Main routine, for testing purposes only.
355      *
356      * @param ignored A String[] with the command line arguments.
357      */
358     public static final void main(String[] ignored)
359     {
360         MD5 md5 = new MD5();
361 
362         for (int i = 0; i < messages.length; i++)
363         {
364             String digest = org.apache.java.lang.Bytes.toString(
365                 md5.digest(messages[i].getBytes()));
366             System.out.println("Computed: " + digest);
367             System.out.println("Correct: " + digests[i]);
368             if (digest.equalsIgnoreCase(digests[i]))
369             {
370                 System.out.println("Test " + i + " passed.");
371             }
372             else
373             {
374                 System.out.println("Test " + i + " failed.");
375             }
376         }
377     }
378 
379     /***
380      * Resets the state of the class.  <b>Beware</b>: calling this
381      * method erases all data previously inserted.
382      */
383     public void reset()
384     {
385         buffer = new byte[64];
386         state = new int[4];
387         x = new int[16];
388 
389         state[0] = 0x67452301;
390         state[1] = 0xefcdab89;
391         state[2] = 0x98badcfe;
392         state[3] = 0x10325476;
393 
394         counter = 0;
395         reminder = 64;
396     }
397 
398     /***
399      * Converts a long to a 8-byte array using low order first.
400      *
401      * @param n A long.
402      * @return A byte[].
403      */
404     public static byte[] toBytes(long n)
405     {
406         byte[] b = new byte[8];
407 
408         b[0] = (byte) (n);
409         n >>>= 8;
410         b[1] = (byte) (n);
411         n >>>= 8;
412         b[2] = (byte) (n);
413         n >>>= 8;
414         b[3] = (byte) (n);
415         n >>>= 8;
416         b[4] = (byte) (n);
417         n >>>= 8;
418         b[5] = (byte) (n);
419         n >>>= 8;
420         b[6] = (byte) (n);
421         n >>>= 8;
422         b[7] = (byte) (n);
423 
424         return b;
425     }
426 
427     /*
428      * TODO: Document.
429      *
430      * @param buffer A byte[].
431      */
432     private void transform(byte[] buffer)
433     {
434         int a, b, c, d;
435 
436         byte2int(buffer, x);
437 
438         a = state[0];
439         b = state[1];
440         c = state[2];
441         d = state[3];
442 
443         a = FF(a, b, c, d, x[ 0],  7, 0xd76aa478);
444         d = FF(d, a, b, c, x[ 1], 12, 0xe8c7b756);
445         c = FF(c, d, a, b, x[ 2], 17, 0x242070db);
446         b = FF(b, c, d, a, x[ 3], 22, 0xc1bdceee);
447         a = FF(a, b, c, d, x[ 4],  7, 0xf57c0faf);
448         d = FF(d, a, b, c, x[ 5], 12, 0x4787c62a);
449         c = FF(c, d, a, b, x[ 6], 17, 0xa8304613);
450         b = FF(b, c, d, a, x[ 7], 22, 0xfd469501);
451         a = FF(a, b, c, d, x[ 8],  7, 0x698098d8);
452         d = FF(d, a, b, c, x[ 9], 12, 0x8b44f7af);
453         c = FF(c, d, a, b, x[10], 17, 0xffff5bb1);
454         b = FF(b, c, d, a, x[11], 22, 0x895cd7be);
455         a = FF(a, b, c, d, x[12],  7, 0x6b901122);
456         d = FF(d, a, b, c, x[13], 12, 0xfd987193);
457         c = FF(c, d, a, b, x[14], 17, 0xa679438e);
458         b = FF(b, c, d, a, x[15], 22, 0x49b40821);
459 
460         a = GG(a, b, c, d, x[ 1],  5, 0xf61e2562);
461         d = GG(d, a, b, c, x[ 6],  9, 0xc040b340);
462         c = GG(c, d, a, b, x[11], 14, 0x265e5a51);
463         b = GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa);
464         a = GG(a, b, c, d, x[ 5],  5, 0xd62f105d);
465         d = GG(d, a, b, c, x[10],  9,  0x2441453);
466         c = GG(c, d, a, b, x[15], 14, 0xd8a1e681);
467         b = GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8);
468         a = GG(a, b, c, d, x[ 9],  5, 0x21e1cde6);
469         d = GG(d, a, b, c, x[14],  9, 0xc33707d6);
470         c = GG(c, d, a, b, x[ 3], 14, 0xf4d50d87);
471         b = GG(b, c, d, a, x[ 8], 20, 0x455a14ed);
472         a = GG(a, b, c, d, x[13],  5, 0xa9e3e905);
473         d = GG(d, a, b, c, x[ 2],  9, 0xfcefa3f8);
474         c = GG(c, d, a, b, x[ 7], 14, 0x676f02d9);
475         b = GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);
476 
477         a = HH(a, b, c, d, x[ 5],  4, 0xfffa3942);
478         d = HH(d, a, b, c, x[ 8], 11, 0x8771f681);
479         c = HH(c, d, a, b, x[11], 16, 0x6d9d6122);
480         b = HH(b, c, d, a, x[14], 23, 0xfde5380c);
481         a = HH(a, b, c, d, x[ 1],  4, 0xa4beea44);
482         d = HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9);
483         c = HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60);
484         b = HH(b, c, d, a, x[10], 23, 0xbebfbc70);
485         a = HH(a, b, c, d, x[13],  4, 0x289b7ec6);
486         d = HH(d, a, b, c, x[ 0], 11, 0xeaa127fa);
487         c = HH(c, d, a, b, x[ 3], 16, 0xd4ef3085);
488         b = HH(b, c, d, a, x[ 6], 23,  0x4881d05);
489         a = HH(a, b, c, d, x[ 9],  4, 0xd9d4d039);
490         d = HH(d, a, b, c, x[12], 11, 0xe6db99e5);
491         c = HH(c, d, a, b, x[15], 16, 0x1fa27cf8);
492         b = HH(b, c, d, a, x[ 2], 23, 0xc4ac5665);
493 
494         a = II(a, b, c, d, x[ 0],  6, 0xf4292244);
495         d = II(d, a, b, c, x[ 7], 10, 0x432aff97);
496         c = II(c, d, a, b, x[14], 15, 0xab9423a7);
497         b = II(b, c, d, a, x[ 5], 21, 0xfc93a039);
498         a = II(a, b, c, d, x[12],  6, 0x655b59c3);
499         d = II(d, a, b, c, x[ 3], 10, 0x8f0ccc92);
500         c = II(c, d, a, b, x[10], 15, 0xffeff47d);
501         b = II(b, c, d, a, x[ 1], 21, 0x85845dd1);
502         a = II(a, b, c, d, x[ 8],  6, 0x6fa87e4f);
503         d = II(d, a, b, c, x[15], 10, 0xfe2ce6e0);
504         c = II(c, d, a, b, x[ 6], 15, 0xa3014314);
505         b = II(b, c, d, a, x[13], 21, 0x4e0811a1);
506         a = II(a, b, c, d, x[ 4],  6, 0xf7537e82);
507         d = II(d, a, b, c, x[11], 10, 0xbd3af235);
508         c = II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb);
509         b = II(b, c, d, a, x[ 9], 21, 0xeb86d391);
510 
511         state[0] += a;
512         state[1] += b;
513         state[2] += c;
514         state[3] += d;
515     }
516 }