View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   //CabaWeb
3   //Copyright (C) 2004  Thomas Vogt <Thomas.Vogt@TVC-Software.com>
4   //
5   //MD5 Java Library
6   //Copyright (C) 1999  Jon Howell <jonh@cs.dartmouth.edu>
7   //
8   //This library is free software; you can redistribute it and/or
9   //modify it under the terms of the GNU Lesser General Public
10  //License as published by the Free Software Foundation; either
11  //version 2.1 of the License, or (at your option) any later version.
12  //
13  //This library 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 GNU
16  //Lesser General Public License for more details.
17  //
18  //You should have received a copy of the GNU Lesser General Public
19  //License along with this library; if not, write to the Free Software
20  //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  ////////////////////////////////////////////////////////////////////////////////
22  
23  package org.fhw.cabaweb.tools;
24  
25  /***
26   * Klasse um MD5 Hashes zu erstellen.
27   * Originalklasse von Jon Howell - mit kleinen &Auml;nderungen von Thomas Vogt
28   *
29   * This class computes MD5 hashes.
30   * Manually translated by Jon Howell <jonh@cs.dartmouth.edu>
31   * from some public domain C code (md5.c) included with the ssh-1.2.22 source.
32   * Tue Jan 19 15:55:50 EST 1999
33   * $Id: MD5.java,v 1.2 2004/11/11 08:44:25 cabaweb Exp $
34   *
35   * To compute the message digest of a chunk of bytes, create an
36   * MD5 object 'md5', call md5.update() as needed on buffers full
37   * of bytes, and then call md5.md5final(), which
38   * will fill a supplied 16-byte array with the digest.
39   *
40   * A main() method is included that hashes the data on System.in.
41   *
42   * It seems to run around 25-30 times slower (JDK1.1.6) than optimized C
43   * (gcc -O4, version 2.7.2.3). Measured on a Sun Ultra 5 (SPARC 270MHz).
44   *
45   * Comments from md5.c from ssh-1.2.22, the basis for this code:
46   *
47   * This code has been heavily hacked by Tatu Ylonen <ylo@cs.hut.fi> to
48   * make it compile on machines like Cray that don't have a 32 bit integer
49   * type.
50   *
51   * This code implements the MD5 message-digest algorithm.
52   * The algorithm is due to Ron Rivest.  This code was
53   * written by Colin Plumb in 1993, no copyright is claimed.
54   * This code is in the public domain; do with it what you wish.
55   *
56   * Equivalent code is available from RSA Data Security, Inc.
57   * This code has been tested against that, and is equivalent,
58   * except that you don't need to include two pages of legalese
59   * with every copy.
60   *
61   * To compute the message digest of a chunk of bytes, declare an
62   * MD5Context structure, pass it to MD5Init, call MD5Update as
63   * needed on buffers full of bytes, and then call MD5Final, which
64   * will fill a supplied 16-byte array with the digest.
65   *
66   * @author	Jon Howell <jonh@cs.dartmouth.edu>
67   * @version	19.01.1999 21:30:11 - Changes 10.03.2004
68   */
69  public class MD5
70  {
71      /***
72       * These were originally unsigned ints.
73       * This Java code makes an effort to avoid sign traps.
74       * buf[] is where the hash accumulates.
75       */
76      private int[] buf;
77      /***
78       * This is the count of bits hashed so far.
79       */
80      private long bits;
81      /***
82       * This is a buffer where we stash bytes until we have
83       * enough (64) to perform a transform operation.
84       */
85      private byte[] in;
86      /***
87       * inint[] used and discarded inside transform(),
88       * but why allocate it over and over?
89       * (In the C version this is allocated on the stack.)
90       */
91      private int[] inint;
92  
93      /***
94       * Konstruktor
95       */
96      public MD5()
97      {
98          buf = new int[4];
99          // fill the hash accumulator with a seed value
100         buf[0] = 0x67452301;
101         buf[1] = 0xefcdab89;
102         buf[2] = 0x98badcfe;
103         buf[3] = 0x10325476;
104 
105         // initially, we've hashed zero bits
106         bits = 0L;
107 
108         in = new byte[64];
109         inint = new int[16];
110     }
111 
112     /***
113      * No Comment
114      */
115     public void update(final byte[] newbuf)
116     {
117         update(newbuf, 0, newbuf.length);
118     }
119 
120     /***
121      * No Comment
122      */
123     public void update(final byte[] newbuf, final int length)
124     {
125         update(newbuf, 0, length);
126     }
127 
128     /***
129      * No Comment
130      */
131     public void update(final byte[] newbuf, int bufstart, final int buflen)
132     {
133         int t;
134         int len = buflen;
135 
136         // shash old bits value for the "Bytes already in" computation
137         // just below.
138         t = (int) bits; // (int) cast should just drop high bits, I hope
139 
140         /* update bitcount */
141         /* the C code used two 32-bit ints separately, and carefully
142          * ensured that the carry carried.
143          * Java has a 64-bit long, which is just what the code really wants.
144          */
145         bits += (long) (len << 3);
146 
147         t = (t >>> 3) & 0x3f; /* Bytes already in this->in */
148 
149         /* Handle any leading odd-sized chunks */
150         /* (that is, any left-over chunk left by last update() */
151 
152         if (t != 0)
153         {
154             int p = t;
155             t = 64 - t;
156             if (len < t)
157             {
158                 System.arraycopy(newbuf, bufstart, in, p, len);
159                 return;
160             }
161             System.arraycopy(newbuf, bufstart, in, p, t);
162             transform();
163             bufstart += t;
164             len -= t;
165         }
166 
167         /* Process data in 64-byte chunks */
168         while (len >= 64)
169         {
170             System.arraycopy(newbuf, bufstart, in, 0, 64);
171             transform();
172             bufstart += 64;
173             len -= 64;
174         }
175 
176         /* Handle any remaining bytes of data. */
177         /* that is, stash them for the next update(). */
178         System.arraycopy(newbuf, bufstart, in, 0, len);
179     }
180 
181     /***
182      * Final wrapup - pad to 64-byte boundary with the bit pattern
183      * 1 0* (64-bit count of bits processed, MSB-first)
184      */
185     public void md5final(final byte[] digest)
186     {
187         /* "final" is a poor method name in Java. :v) */
188         int count;
189         int p; // in original code, this is a pointer; in this java code
190         // it's an index into the array this->in.
191 
192         /* Compute number of bytes mod 64 */
193         count = (int) ((bits >>> 3) & 0x3F);
194 
195         /* Set the first char of padding to 0x80.  This is safe since there is
196            always at least one byte free */
197         p = count;
198         in[p++] = (byte) 0x80;
199 
200         /* Bytes of padding needed to make 64 bytes */
201         count = 64 - 1 - count;
202 
203         /* Pad out to 56 mod 64 */
204         if (count < 8)
205         {
206             /* Two lots of padding:  Pad the first block to 64 bytes */
207             zeroByteArray(in, p, count);
208             transform();
209 
210             /* Now fill the next block with 56 bytes */
211             zeroByteArray(in, 0, 56);
212         }
213         else
214         {
215             /* Pad block to 56 bytes */
216             zeroByteArray(in, p, count - 8);
217         }
218 
219         /* Append length in bits and transform */
220         // Could use a PUT_64BIT... func here. This is a fairly
221         // direct translation from the C code, where bits was an array
222         // of two 32-bit ints.
223         int lowbits = (int) bits;
224         int highbits = (int) (bits >>> 32);
225         PUT_32BIT_LSB_FIRST(in, 56, lowbits);
226         PUT_32BIT_LSB_FIRST(in, 60, highbits);
227 
228         transform();
229         PUT_32BIT_LSB_FIRST(digest, 0, buf[0]);
230         PUT_32BIT_LSB_FIRST(digest, 4, buf[1]);
231         PUT_32BIT_LSB_FIRST(digest, 8, buf[2]);
232         PUT_32BIT_LSB_FIRST(digest, 12, buf[3]);
233 
234         /* zero sensitive data */
235         /* notice this misses any sneaking out on the stack. The C
236          * version uses registers in some spots, perhaps because
237          * they care about this.
238          */
239         zeroByteArray(in);
240         zeroIntArray(buf);
241         bits = 0;
242         zeroIntArray(inint);
243     }
244 
245     /***
246      * No Comment
247      */
248     public String dumpBytes(final byte[] bytes)
249     {
250         int i;
251         StringBuffer sb = new StringBuffer();
252         for (i = 0; i < bytes.length; i++)
253         {
254             if (i % 32 == 0 && i != 0)
255             {
256                 sb.append("\n");
257             }
258             String s = Integer.toHexString(bytes[i]);
259             if (s.length() < 2)
260             {
261                 s = "0" + s;
262             }
263             if (s.length() > 2)
264             {
265                 s = s.substring(s.length() - 2);
266             }
267             sb.append(s);
268         }
269         return sb.toString();
270     }
271 
272     /////////////////////////////////////////////////////////////////////
273     // Below here ye will only finde private functions                 //
274     /////////////////////////////////////////////////////////////////////
275 
276     // There must be a way to do these functions that's
277     // built into Java, and I just haven't noticed it yet.
278 
279     /***
280      * No Comment
281      */
282     private void zeroByteArray(final byte[] a)
283     {
284         zeroByteArray(a, 0, a.length);
285     }
286 
287     /***
288      * No Comment
289      */
290     private void zeroByteArray(final byte[] a, final int start, final int length)
291     {
292         setByteArray(a, (byte) 0, start, length);
293     }
294 
295     /***
296      * No Comment
297      */
298     private void setByteArray(final byte[] a, final byte val, final int start, final int length)
299     {
300         int i;
301         int end = start + length;
302         for (i = start; i < end; i++)
303         {
304             a[i] = val;
305         }
306     }
307 
308     /***
309      * No Comment
310      */
311     private void zeroIntArray(final int[] a)
312     {
313         zeroIntArray(a, 0, a.length);
314     }
315 
316     /***
317      * No Comment
318      */
319     private void zeroIntArray(final int[] a, final int start, final int length)
320     {
321         setIntArray(a, (int) 0, start, length);
322     }
323 
324     /***
325      * No Comment
326      */
327     private void setIntArray(final int[] a, final int val, final int start, final int length)
328     {
329         int i;
330         int end = start + length;
331         for (i = start; i < end; i++)
332         {
333             a[i] = val;
334         }
335     }
336 
337     // In the C version, a call to MD5STEP is a macro-in-a-macro.
338     // In this Java version, we pass an Fcore object to represent the
339     // inner macro, and the MD5STEP() method performs the work of
340     // the outer macro. It would be good if this could all get
341     // inlined, but it would take a pretty aggressive compiler to
342     // inline away the dynamic method lookup made by MD5STEP to
343     // get to the Fcore.f function.
344 
345     /***
346      * No Comment
347      */
348     private abstract class Fcore
349     {
350         abstract int f(final int x, final int y, final int z);
351     }
352 
353     /***
354      * No Comment
355      */
356     private Fcore F1 = new Fcore()
357     {
358         int f(final int x, final int y, final int z)
359         {
360             return (z ^ (x & (y ^ z)));
361         }
362     };
363 
364     /***
365      * No Comment
366      */
367     private Fcore F2 = new Fcore()
368     {
369         int f(final int x, final int y, final int z)
370         {
371             return (y ^ (z & (x ^ y)));
372         }
373     };
374 
375     /***
376      * No Comment
377      */
378     private Fcore F3 = new Fcore()
379     {
380         int f(final int x, final int y, final int z)
381         {
382             return (x ^ y ^ z);
383         }
384     };
385 
386     /***
387      * No Comment
388      */
389     private Fcore F4 = new Fcore()
390     {
391         int f(final int x, final int y, final int z)
392         {
393             return (y ^ (x | ~z));
394         }
395     };
396 
397     /***
398      * No Comment
399      */
400     private int MD5STEP(final Fcore f, int w, final int x, final int y, final int z, final int data, final int s)
401     {
402         w += f.f(x, y, z) + data;
403         w = w << s | w >>> (32 - s);
404         w += x;
405         return w;
406     }
407 
408     /***
409      * No Comment
410      */
411     private void transform()
412     {
413         /* load in[] byte array into an internal int array */
414         int i;
415         int[] inint = new int[16];
416 
417         for (i = 0; i < 16; i++)
418         {
419             inint[i] = GET_32BIT_LSB_FIRST(in, 4 * i);
420         }
421 
422         int a, b, c, d;
423         a = buf[0];
424         b = buf[1];
425         c = buf[2];
426         d = buf[3];
427 
428         a = MD5STEP(F1, a, b, c, d, inint[0] + 0xd76aa478, 7);
429         d = MD5STEP(F1, d, a, b, c, inint[1] + 0xe8c7b756, 12);
430         c = MD5STEP(F1, c, d, a, b, inint[2] + 0x242070db, 17);
431         b = MD5STEP(F1, b, c, d, a, inint[3] + 0xc1bdceee, 22);
432         a = MD5STEP(F1, a, b, c, d, inint[4] + 0xf57c0faf, 7);
433         d = MD5STEP(F1, d, a, b, c, inint[5] + 0x4787c62a, 12);
434         c = MD5STEP(F1, c, d, a, b, inint[6] + 0xa8304613, 17);
435         b = MD5STEP(F1, b, c, d, a, inint[7] + 0xfd469501, 22);
436         a = MD5STEP(F1, a, b, c, d, inint[8] + 0x698098d8, 7);
437         d = MD5STEP(F1, d, a, b, c, inint[9] + 0x8b44f7af, 12);
438         c = MD5STEP(F1, c, d, a, b, inint[10] + 0xffff5bb1, 17);
439         b = MD5STEP(F1, b, c, d, a, inint[11] + 0x895cd7be, 22);
440         a = MD5STEP(F1, a, b, c, d, inint[12] + 0x6b901122, 7);
441         d = MD5STEP(F1, d, a, b, c, inint[13] + 0xfd987193, 12);
442         c = MD5STEP(F1, c, d, a, b, inint[14] + 0xa679438e, 17);
443         b = MD5STEP(F1, b, c, d, a, inint[15] + 0x49b40821, 22);
444 
445         a = MD5STEP(F2, a, b, c, d, inint[1] + 0xf61e2562, 5);
446         d = MD5STEP(F2, d, a, b, c, inint[6] + 0xc040b340, 9);
447         c = MD5STEP(F2, c, d, a, b, inint[11] + 0x265e5a51, 14);
448         b = MD5STEP(F2, b, c, d, a, inint[0] + 0xe9b6c7aa, 20);
449         a = MD5STEP(F2, a, b, c, d, inint[5] + 0xd62f105d, 5);
450         d = MD5STEP(F2, d, a, b, c, inint[10] + 0x02441453, 9);
451         c = MD5STEP(F2, c, d, a, b, inint[15] + 0xd8a1e681, 14);
452         b = MD5STEP(F2, b, c, d, a, inint[4] + 0xe7d3fbc8, 20);
453         a = MD5STEP(F2, a, b, c, d, inint[9] + 0x21e1cde6, 5);
454         d = MD5STEP(F2, d, a, b, c, inint[14] + 0xc33707d6, 9);
455         c = MD5STEP(F2, c, d, a, b, inint[3] + 0xf4d50d87, 14);
456         b = MD5STEP(F2, b, c, d, a, inint[8] + 0x455a14ed, 20);
457         a = MD5STEP(F2, a, b, c, d, inint[13] + 0xa9e3e905, 5);
458         d = MD5STEP(F2, d, a, b, c, inint[2] + 0xfcefa3f8, 9);
459         c = MD5STEP(F2, c, d, a, b, inint[7] + 0x676f02d9, 14);
460         b = MD5STEP(F2, b, c, d, a, inint[12] + 0x8d2a4c8a, 20);
461 
462         a = MD5STEP(F3, a, b, c, d, inint[5] + 0xfffa3942, 4);
463         d = MD5STEP(F3, d, a, b, c, inint[8] + 0x8771f681, 11);
464         c = MD5STEP(F3, c, d, a, b, inint[11] + 0x6d9d6122, 16);
465         b = MD5STEP(F3, b, c, d, a, inint[14] + 0xfde5380c, 23);
466         a = MD5STEP(F3, a, b, c, d, inint[1] + 0xa4beea44, 4);
467         d = MD5STEP(F3, d, a, b, c, inint[4] + 0x4bdecfa9, 11);
468         c = MD5STEP(F3, c, d, a, b, inint[7] + 0xf6bb4b60, 16);
469         b = MD5STEP(F3, b, c, d, a, inint[10] + 0xbebfbc70, 23);
470         a = MD5STEP(F3, a, b, c, d, inint[13] + 0x289b7ec6, 4);
471         d = MD5STEP(F3, d, a, b, c, inint[0] + 0xeaa127fa, 11);
472         c = MD5STEP(F3, c, d, a, b, inint[3] + 0xd4ef3085, 16);
473         b = MD5STEP(F3, b, c, d, a, inint[6] + 0x04881d05, 23);
474         a = MD5STEP(F3, a, b, c, d, inint[9] + 0xd9d4d039, 4);
475         d = MD5STEP(F3, d, a, b, c, inint[12] + 0xe6db99e5, 11);
476         c = MD5STEP(F3, c, d, a, b, inint[15] + 0x1fa27cf8, 16);
477         b = MD5STEP(F3, b, c, d, a, inint[2] + 0xc4ac5665, 23);
478 
479         a = MD5STEP(F4, a, b, c, d, inint[0] + 0xf4292244, 6);
480         d = MD5STEP(F4, d, a, b, c, inint[7] + 0x432aff97, 10);
481         c = MD5STEP(F4, c, d, a, b, inint[14] + 0xab9423a7, 15);
482         b = MD5STEP(F4, b, c, d, a, inint[5] + 0xfc93a039, 21);
483         a = MD5STEP(F4, a, b, c, d, inint[12] + 0x655b59c3, 6);
484         d = MD5STEP(F4, d, a, b, c, inint[3] + 0x8f0ccc92, 10);
485         c = MD5STEP(F4, c, d, a, b, inint[10] + 0xffeff47d, 15);
486         b = MD5STEP(F4, b, c, d, a, inint[1] + 0x85845dd1, 21);
487         a = MD5STEP(F4, a, b, c, d, inint[8] + 0x6fa87e4f, 6);
488         d = MD5STEP(F4, d, a, b, c, inint[15] + 0xfe2ce6e0, 10);
489         c = MD5STEP(F4, c, d, a, b, inint[6] + 0xa3014314, 15);
490         b = MD5STEP(F4, b, c, d, a, inint[13] + 0x4e0811a1, 21);
491         a = MD5STEP(F4, a, b, c, d, inint[4] + 0xf7537e82, 6);
492         d = MD5STEP(F4, d, a, b, c, inint[11] + 0xbd3af235, 10);
493         c = MD5STEP(F4, c, d, a, b, inint[2] + 0x2ad7d2bb, 15);
494         b = MD5STEP(F4, b, c, d, a, inint[9] + 0xeb86d391, 21);
495 
496         buf[0] += a;
497         buf[1] += b;
498         buf[2] += c;
499         buf[3] += d;
500     }
501 
502     /***
503      * No Comment
504      */
505     private int GET_32BIT_LSB_FIRST(final byte[] b, final int off)
506     {
507         return ((int) (b[off + 0] & 0xff)) | ((int) (b[off + 1] & 0xff) << 8) | ((int) (b[off + 2] & 0xff) << 16) | ((int) (b[off + 3] & 0xff) << 24);
508     }
509 
510     /***
511      * No Comment
512      */
513     private void PUT_32BIT_LSB_FIRST(final byte[] b, final int off, final int value)
514     {
515         b[off + 0] = (byte) (value & 0xff);
516         b[off + 1] = (byte) ((value >> 8) & 0xff);
517         b[off + 2] = (byte) ((value >> 16) & 0xff);
518         b[off + 3] = (byte) ((value >> 24) & 0xff);
519     }
520 
521     /***
522      * These are debug routines I was using while trying to
523      * get this code to generate the same hashes as the C version.
524      * (IIRC, all the errors were due to the absence of unsigned
525      * ints in Java.)
526      *
527      * @deprecated
528      */
529     private void debugStatus(String m)
530     {
531         System.out.println(m + ":");
532         System.out.println("in: " + dumpBytes(in));
533         System.out.println("bits: " + bits);
534         System.out.println("buf: " + Integer.toHexString(buf[0]) + " " + Integer.toHexString(buf[1]) + " " + Integer.toHexString(buf[2]) + " " + Integer.toHexString(buf[3]));
535     }
536 }