KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > knowgate > misc > MD5


1 package com.knowgate.misc;
2
3 import com.knowgate.debug.DebugFile;
4
5 /*
6  * $Header: /cvsroot/hipergate/backend/src/com/knowgate/misc/MD5.java,v 1.1.1.1 2005/06/23 15:15:08 smontoro Exp $
7  *
8  * MD5 in Java JDK Beta-2
9  * written Santeri Paavolainen, Helsinki Finland 1996
10  * (c) Santeri Paavolainen, Helsinki Finland 1996
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with this library; if not, write to the Free
24  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25  *
26  * See http://www.cs.hut.fi/~santtu/java/ for more information on this
27  * class.
28  *
29  * This is rather straight re-implementation of the reference implementation
30  * given in RFC1321 by RSA.
31  *
32  * Passes MD5 test suite as defined in RFC1321.
33  *
34  *
35  * This Java class has been derived from the RSA Data Security, Inc. MD5
36  * Message-Digest Algorithm and its reference implementation.
37  *
38  * Revision 1.1 1996/01/07 20:51:59 santtu
39  * Initial revision
40  *
41  */

42
43 /**
44  * Contains internal state of the MD5 class
45  */

46
47 class MD5State {
48   /**
49    * 128-byte state
50    */

51   int state[];
52
53   /**
54    * 64-bit character count (could be true Java long?)
55    */

56   int count[];
57
58   /**
59    * 64-byte buffer (512 bits) for storing to-be-hashed characters
60    */

61   byte buffer[];
62
63   public MD5State() {
64     buffer = new byte[64];
65     count = new int[2];
66     state = new int[4];
67
68     state[0] = 0x67452301;
69     state[1] = 0xefcdab89;
70     state[2] = 0x98badcfe;
71     state[3] = 0x10325476;
72
73     count[0] = count[1] = 0;
74   }
75
76   /** Create this State as a copy of another state */
77   public MD5State (MD5State from) {
78     this();
79
80     int i;
81
82     for (i = 0; i < buffer.length; i++)
83       this.buffer[i] = from.buffer[i];
84
85     for (i = 0; i < state.length; i++)
86       this.state[i] = from.state[i];
87
88     for (i = 0; i < count.length; i++)
89       this.count[i] = from.count[i];
90   }
91 }
92
93 /**
94  * Implementation of RSA's MD5 hash generator
95  *
96  * @version $Revision: 1.1.1.1 $
97  * @author Santeri Paavolainen <sjpaavol@cc.helsinki.fi>
98  */

99
100 public class MD5 {
101   /**
102    * MD5 state
103    */

104   MD5State state;
105
106   /**
107    * If Final() has been called, finals is set to the current finals
108    * state. Any Update() causes this to be set to null.
109    */

110   MD5State finals;
111
112   /**
113    * Padding for Final()
114    */

115   static byte padding[] = {
116     (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
117     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
118     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
119   };
120
121   /**
122    * Initialize MD5 internal state (object can be reused just by
123    * calling Init() after every Final()
124    */

125   public synchronized void Init () {
126     state = new MD5State();
127     finals = null;
128   }
129
130   /**
131    * Class constructor
132    */

133   public MD5 () {
134     this.Init();
135   }
136
137   /**
138    * Initialize class, and update hash with ob.toString()
139    *
140    * @param ob Object, ob.toString() is used to update hash
141    * after initialization
142    */

143   public MD5 (Object JavaDoc ob) {
144     this();
145     Update(ob.toString());
146   }
147
148   private int rotate_left (int x, int n) {
149     return (x << n) | (x >>> (32 - n));
150   }
151
152   /* I wonder how many loops and hoops you'll have to go through to
153      get unsigned add for longs in java */

154
155   private int uadd (int a, int b) {
156     long aa, bb;
157     aa = ((long) a) & 0xffffffffL;
158     bb = ((long) b) & 0xffffffffL;
159
160     aa += bb;
161
162     return (int) (aa & 0xffffffffL);
163   }
164
165   private int uadd (int a, int b, int c) {
166     return uadd(uadd(a, b), c);
167   }
168
169   private int uadd (int a, int b, int c, int d) {
170     return uadd(uadd(a, b, c), d);
171   }
172
173   private int FF (int a, int b, int c, int d, int x, int s, int ac) {
174     a = uadd(a, ((b & c) | (~b & d)), x, ac);
175     return uadd(rotate_left(a, s), b);
176   }
177
178   private int GG (int a, int b, int c, int d, int x, int s, int ac) {
179     a = uadd(a, ((b & d) | (c & ~d)), x, ac);
180     return uadd(rotate_left(a, s), b);
181   }
182
183   private int HH (int a, int b, int c, int d, int x, int s, int ac) {
184     a = uadd(a, (b ^ c ^ d), x, ac);
185     return uadd(rotate_left(a, s) , b);
186   }
187
188   private int II (int a, int b, int c, int d, int x, int s, int ac) {
189     a = uadd(a, (c ^ (b | ~d)), x, ac);
190     return uadd(rotate_left(a, s), b);
191   }
192
193   private int[] Decode (byte buffer[], int len, int shift) {
194     int out[];
195     int i, j;
196
197     out = new int[16];
198
199     for (i = j = 0; j < len; i++, j += 4) {
200       out[i] = ((int) (buffer[j + shift] & 0xff)) |
201     (((int) (buffer[j + 1 + shift] & 0xff)) << 8) |
202     (((int) (buffer[j + 2 + shift] & 0xff)) << 16) |
203     (((int) (buffer[j + 3 + shift] & 0xff)) << 24);
204
205 /* System.out.println("out[" + i + "] = \t" +
206              ((int) buffer[j + 0 + shift] & 0xff) + "\t|\t" +
207              ((int) buffer[j + 1 + shift] & 0xff) + "\t|\t" +
208              ((int) buffer[j + 2 + shift] & 0xff) + "\t|\t" +
209              ((int) buffer[j + 3 + shift] & 0xff));*/

210     }
211
212     return out;
213   }
214
215   private void Transform (MD5State state, byte buffer[], int shift) {
216     int
217       a = state.state[0],
218       b = state.state[1],
219       c = state.state[2],
220       d = state.state[3],
221       x[];
222
223     x = Decode(buffer, 64, shift);
224
225     /* Round 1 */
226     a = FF (a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */
227     d = FF (d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */
228     c = FF (c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */
229     b = FF (b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */
230     a = FF (a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */
231     d = FF (d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */
232     c = FF (c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */
233     b = FF (b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */
234     a = FF (a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */
235     d = FF (d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */
236     c = FF (c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
237     b = FF (b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
238     a = FF (a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
239     d = FF (d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
240     c = FF (c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
241     b = FF (b, c, d, a, x[15], 22, 0x49b40821); /* 16 */
242
243     /* Round 2 */
244     a = GG (a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */
245     d = GG (d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */
246     c = GG (c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
247     b = GG (b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */
248     a = GG (a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */
249     d = GG (d, a, b, c, x[10], 9, 0x2441453); /* 22 */
250     c = GG (c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
251     b = GG (b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */
252     a = GG (a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */
253     d = GG (d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
254     c = GG (c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */
255     b = GG (b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */
256     a = GG (a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
257     d = GG (d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */
258     c = GG (c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */
259     b = GG (b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */
260
261     /* Round 3 */
262     a = HH (a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */
263     d = HH (d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */
264     c = HH (c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
265     b = HH (b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
266     a = HH (a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */
267     d = HH (d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */
268     c = HH (c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */
269     b = HH (b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
270     a = HH (a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
271     d = HH (d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */
272     c = HH (c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */
273     b = HH (b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */
274     a = HH (a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */
275     d = HH (d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
276     c = HH (c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
277     b = HH (b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */
278
279     /* Round 4 */
280     a = II (a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */
281     d = II (d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */
282     c = II (c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
283     b = II (b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */
284     a = II (a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
285     d = II (d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */
286     c = II (c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
287     b = II (b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */
288     a = II (a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */
289     d = II (d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
290     c = II (c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */
291     b = II (b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
292     a = II (a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */
293     d = II (d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
294     c = II (c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */
295     b = II (b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */
296
297     state.state[0] += a;
298     state.state[1] += b;
299     state.state[2] += c;
300     state.state[3] += d;
301   }
302
303   /**
304    * Updates hash with the bytebuffer given (using at maximum length bytes from
305    * that buffer)
306    *
307    * @param state Which state is updated
308    * @param buffer Array of bytes to be hashed
309    * @param offset Offset to buffer array
310    * @param length Use at maximum `length' bytes (absolute
311    * maximum is buffer.length)
312    */

313   public void Update (MD5State stat, byte buffer[], int offset, int length)
314     throws NullPointerException JavaDoc {
315     int index, partlen, i, start;
316
317     if (null==buffer) throw new NullPointerException JavaDoc("Array of bytes to be hashed may not be null");
318
319     if (DebugFile.trace) {
320       DebugFile.writeln("Begin MD5.Update([MD5State],byte[],"+String.valueOf(offset)+","+String.valueOf(length)+")");
321       DebugFile.incIdent();
322     }
323
324     finals = null;
325
326     /* Length can be told to be shorter, but not inter */
327     if ((length - offset)> buffer.length)
328       length = buffer.length - offset;
329
330     /* compute number of bytes mod 64 */
331     index = (int) (stat.count[0] >>> 3) & 0x3f;
332
333     if ((stat.count[0] += (length << 3)) <
334     (length << 3))
335       stat.count[1]++;
336
337     stat.count[1] += length >>> 29;
338
339     partlen = 64 - index;
340
341     if (length >= partlen) {
342       for (i = 0; i < partlen; i++)
343     stat.buffer[i + index] = buffer[i + offset];
344
345       Transform(stat, stat.buffer, 0);
346
347       for (i = partlen; (i + 63) < length; i+= 64)
348     Transform(stat, buffer, i);
349
350       index = 0;
351     } else
352       i = 0;
353
354     /* buffer remaining input */
355     if (i < length) {
356       start = i;
357       for (; i < length; i++)
358     stat.buffer[index + i - start] = buffer[i + offset];
359     }
360
361     if (DebugFile.trace) {
362       DebugFile.decIdent();
363       DebugFile.writeln("End MD5.Update()");
364     }
365   } // Update
366

367   /*
368    * Update()s for other datatypes than byte[] also. Update(byte[], int)
369    * is only the main driver.
370    */

371
372   /**
373    * Plain update, updates this object
374    */

375
376   public void Update (byte buffer[], int offset, int length) {
377       Update(this.state, buffer, offset, length);
378   }
379
380   public void Update (byte buffer[], int length) {
381       Update(this.state, buffer, 0, length);
382   }
383
384   /**
385    * Updates hash with given array of bytes
386    *
387    * @param buffer Array of bytes to use for updating the hash
388    */

389   public void Update (byte buffer[]) throws NullPointerException JavaDoc {
390       if (null==buffer) throw new NullPointerException JavaDoc("Array of bytes to be hashed may not be null");
391
392       Update(buffer, 0, buffer.length);
393   }
394
395   /**
396    * Updates hash with a single byte
397    *
398    * @param b Single byte to update the hash
399    */

400   public void Update (byte b) {
401     byte buffer[] = new byte[1];
402     buffer[0] = b;
403
404     Update(buffer, 1);
405   }
406
407   /**
408    * Update buffer with given string.
409    *
410    * @param s String to be update to hash (is used as
411    * s.getBytes())
412    */

413   public void Update (String JavaDoc s) {
414     byte chars[];
415
416 // chars = new byte[s.length()];
417
// s.getBytes(0, s.length(), chars, 0);
418
try {
419     chars = s.getBytes("UTF-8");
420     } catch(java.io.UnsupportedEncodingException JavaDoc ex) {
421     // Should never happen
422
ex.printStackTrace();
423     chars = new byte[1];
424     }
425
426     Update(chars, chars.length);
427   }
428
429   /**
430    * Update buffer with a single integer (only & 0xff part is used,
431    * as a byte)
432    *
433    * @param i Integer value, which is then converted to
434    * byte as i & 0xff
435    */

436
437   public void Update (int i) {
438       Update((byte) (i & 0xff));
439   }
440
441   private byte[] Encode (int input[], int len) {
442     int i, j;
443     byte out[];
444
445     out = new byte[len];
446
447     for (i = j = 0; j < len; i++, j += 4) {
448       out[j] = (byte) (input[i] & 0xff);
449       out[j + 1] = (byte) ((input[i] >>> 8) & 0xff);
450       out[j + 2] = (byte) ((input[i] >>> 16) & 0xff);
451       out[j + 3] = (byte) ((input[i] >>> 24) & 0xff);
452     }
453
454     return out;
455   }
456
457   /**
458    * Returns array of bytes (16 bytes) representing hash as of the
459    * current state of this object. Note: getting a hash does not
460    * invalidate the hash object, it only creates a copy of the real
461    * state which is finalized.
462    *
463    * @return Array of 16 bytes, the hash of all updated bytes
464    */

465   public synchronized byte[] Final () {
466     byte bits[];
467     int index, padlen;
468     MD5State fin;
469
470     if (finals == null) {
471       fin = new MD5State(state);
472
473       bits = Encode(fin.count, 8);
474
475       index = (int) ((fin.count[0] >>> 3) & 0x3f);
476       padlen = (index < 56) ? (56 - index) : (120 - index);
477
478       Update(fin, padding, 0, padlen);
479       /**/
480       Update(fin, bits, 0, 8);
481
482       /* Update() sets finalds to null */
483       finals = fin;
484     }
485
486     byte[] byRetArray = Encode(finals.state, 16);
487
488     if (DebugFile.trace) DebugFile.writeln("MD5.Final() : " + Gadgets.toHexString(byRetArray));
489
490     return byRetArray;
491   }
492
493   /**
494    * Turns array of bytes into string representing each byte as
495    * unsigned hex number.
496    *
497    * @param hash Array of bytes to convert to hex-string
498    * @return Generated hex string
499    */

500   public static String JavaDoc asHex (byte hash[]) {
501     StringBuffer JavaDoc buf = new StringBuffer JavaDoc(hash.length * 2);
502     int i;
503
504     for (i = 0; i < hash.length; i++) {
505       if (((int) hash[i] & 0xff) < 0x10)
506     buf.append("0");
507
508       buf.append(Long.toString((int) hash[i] & 0xff, 16));
509     }
510
511     return buf.toString();
512   }
513
514   /**
515    * Returns 32-character hex representation of this objects hash
516    *
517    * @return String of this object's hash
518    */

519   public String JavaDoc asHex () {
520     return asHex(this.Final());
521   }
522 }
523
Popular Tags