KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > chateverywhere > MD5


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

34
35 package org.chateverywhere;
36
37 /**
38  * Contains internal state of the MD5 class
39  */

40
41 class MD5State {
42   /**
43    * 128-byte state
44    */

45   int state[];
46
47   /**
48    * 64-bit character count (could be true Java long?)
49    */

50   int count[];
51
52   /**
53    * 64-byte buffer (512 bits) for storing to-be-hashed characters
54    */

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

93
94 public class MD5 {
95   /**
96    * MD5 state
97    */

98   MD5State state;
99  
100   /**
101    * If Final() has been called, finals is set to the current finals
102    * state. Any Update() causes this to be set to null.
103    */

104   MD5State finals;
105
106   /**
107    * Padding for Final()
108    */

109   static byte padding[] = {
110     (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
113   };
114
115   /**
116    * Initialize MD5 internal state (object can be reused just by
117    * calling Init() after every Final()
118    */

119   public synchronized void Init () {
120     state = new MD5State();
121     finals = null;
122   }
123
124   /**
125    * Class constructor
126    */

127   public MD5 () {
128     this.Init();
129   }
130
131   /**
132    * Initialize class, and update hash with ob.toString()
133    *
134    * @param ob Object, ob.toString() is used to update hash
135    * after initialization
136    */

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

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

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

307   public void Update (MD5State stat, byte buffer[], int offset, int length) {
308     int index, partlen, i, start;
309
310 /* System.out.print("Offset = " + offset + "\tLength = " + length + "\t");
311     System.out.print("Buffer = ");
312     for (i = 0; i < buffer.length; i++)
313     System.out.print((int) (buffer[i] & 0xff) + " ");
314     System.out.print("\n");*/

315
316     finals = null;
317
318     /* Length can be told to be shorter, but not inter */
319     if ((length - offset)> buffer.length)
320       length = buffer.length - offset;
321
322     /* compute number of bytes mod 64 */
323     index = (int) (stat.count[0] >>> 3) & 0x3f;
324
325     if ((stat.count[0] += (length << 3)) <
326     (length << 3))
327       stat.count[1]++;
328
329     stat.count[1] += length >>> 29;
330
331     partlen = 64 - index;
332
333     if (length >= partlen) {
334       for (i = 0; i < partlen; i++)
335     stat.buffer[i + index] = buffer[i + offset];
336
337       Transform(stat, stat.buffer, 0);
338     
339       for (i = partlen; (i + 63) < length; i+= 64)
340     Transform(stat, buffer, i);
341
342       index = 0;
343     } else
344       i = 0;
345
346     /* buffer remaining input */
347     if (i < length) {
348       start = i;
349       for (; i < length; i++)
350     stat.buffer[index + i - start] = buffer[i + offset];
351     }
352   }
353
354   /*
355    * Update()s for other datatypes than byte[] also. Update(byte[], int)
356    * is only the main driver.
357    */

358
359   /**
360    * Plain update, updates this object
361    */

362
363   public void Update (byte buffer[], int offset, int length) {
364       Update(this.state, buffer, offset, length);
365   }
366
367   public void Update (byte buffer[], int length) {
368       Update(this.state, buffer, 0, length);
369   }
370
371   /**
372    * Updates hash with given array of bytes
373    *
374    * @param buffer Array of bytes to use for updating the hash
375    */

376   public void Update (byte buffer[]) {
377       Update(buffer, 0, buffer.length);
378   }
379
380   /**
381    * Updates hash with a single byte
382    *
383    * @param b Single byte to update the hash
384    */

385   public void Update (byte b) {
386     byte buffer[] = new byte[1];
387     buffer[0] = b;
388
389     Update(buffer, 1);
390   }
391   
392   /**
393    * Update buffer with given string.
394    *
395    * @param s String to be update to hash (is used as
396    * s.getBytes())
397    */

398   public void Update (String JavaDoc s) {
399     byte chars[];
400     int i;
401
402     chars = new byte[s.length()];
403     // MS-IE JVM does not like a specific encoding
404
chars = s.getBytes();
405
406     Update(chars, chars.length);
407   }
408
409   /**
410    * Update buffer with a single integer (only & 0xff part is used,
411    * as a byte)
412    *
413    * @param i Integer value, which is then converted to
414    * byte as i & 0xff
415    */

416
417   public void Update (int i) {
418       Update((byte) (i & 0xff));
419   }
420
421   private byte[] Encode (int input[], int len) {
422     int i, j;
423     byte out[];
424
425     out = new byte[len];
426
427     for (i = j = 0; j < len; i++, j += 4) {
428       out[j] = (byte) (input[i] & 0xff);
429       out[j + 1] = (byte) ((input[i] >>> 8) & 0xff);
430       out[j + 2] = (byte) ((input[i] >>> 16) & 0xff);
431       out[j + 3] = (byte) ((input[i] >>> 24) & 0xff);
432     }
433
434     return out;
435   }
436
437   /**
438    * Returns array of bytes (16 bytes) representing hash as of the
439    * current state of this object. Note: getting a hash does not
440    * invalidate the hash object, it only creates a copy of the real
441    * state which is finalized.
442    *
443    * @return Array of 16 bytes, the hash of all updated bytes
444    */

445   public synchronized byte[] Final () {
446     byte bits[];
447     int index, padlen;
448     MD5State fin;
449
450     if (finals == null) {
451       fin = new MD5State(state);
452
453       bits = Encode(fin.count, 8);
454     
455       index = (int) ((fin.count[0] >>> 3) & 0x3f);
456       padlen = (index < 56) ? (56 - index) : (120 - index);
457
458       Update(fin, padding, 0, padlen);
459       /**/
460       Update(fin, bits, 0, 8);
461
462       /* Update() sets finalds to null */
463       finals = fin;
464     }
465
466     return Encode(finals.state, 16);
467   }
468
469   /**
470    * Turns array of bytes into string representing each byte as
471    * unsigned hex number.
472    *
473    * @param hash Array of bytes to convert to hex-string
474    * @return Generated hex string
475    */

476   public static String JavaDoc asHex (byte hash[]) {
477     StringBuffer JavaDoc buf = new StringBuffer JavaDoc(hash.length * 2);
478     int i;
479
480     for (i = 0; i < hash.length; i++) {
481       if (((int) hash[i] & 0xff) < 0x10)
482     buf.append("0");
483
484       buf.append(Long.toString((int) hash[i] & 0xff, 16));
485     }
486
487     return buf.toString();
488   }
489
490   /**
491    * Returns 32-character hex representation of this objects hash
492    *
493    * @return String of this object's hash
494    */

495   public String JavaDoc asHex () {
496     return asHex(this.Final());
497   }
498 }
499
Popular Tags