Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: plugins/MsnEngine/MD5.java


1   /*
2   This file is part of DeXter - Java Internet Communication Solution
3   Copyright (c) 2002 Tobias Riemer
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  GNU General Public License for more details.
14  
15  You should have received a copy of the GNU Lesser General Public
16  License along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  */
19  
20  package plugins.MsnEngine;
21  
22  /*
23   * $Header: /cvsroot/jdexter/plugins/MsnEngine/MD5.java,v 1.3 2002/10/28 21:35:41 saintedlama Exp $
24   *
25   * MD5 in Java JDK Beta-2
26   * written Santeri Paavolainen, Helsinki Finland 1996
27   * (c) Santeri Paavolainen, Helsinki Finland 1996
28   *
29   * This library is free software; you can redistribute it and/or
30   * modify it under the terms of the GNU Library General Public
31   * License as published by the Free Software Foundation; either
32   * version 2 of the License, or (at your option) any later version.
33   *
34   * This library is distributed in the hope that it will be useful,
35   * but WITHOUT ANY WARRANTY; without even the implied warranty of
36   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
37   * Library General Public License for more details.
38   *
39   * You should have received a copy of the GNU Library General Public
40   * License along with this library; if not, write to the Free
41   * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
42   *
43   * See http://www.cs.hut.fi/~santtu/java/ for more information on this
44   * class.
45   *
46   * This is rather straight re-implementation of the reference implementation
47   * given in RFC1321 by RSA.
48   *
49   * Passes MD5 test suite as defined in RFC1321.
50   *
51   *
52   * This Java class has been derived from the RSA Data Security, Inc. MD5
53   * Message-Digest Algorithm and its reference implementation.
54   *
55   *
56   * $Log: MD5.java,v $
57   * Revision 1.3  2002/10/28 21:35:41  saintedlama
58   *
59   * License Header inserted
60   *
61   * Revision 1.2  2002/10/27 14:44:32  saintedlama
62   *
63   * Made MD5State an inner Class of MD5
64   *
65   * Revision 1.1  2002/10/21 18:02:28  tobias_r
66   * *** empty log message ***
67   *
68   * Revision 1.1.1.1  2002/10/16 22:10:49  tobias_r
69   *
70   *
71   * Revision 1.5  1996/12/12 10:47:02  santtu
72   * Changed GPL to LGPL
73   *
74   * Revision 1.4  1996/12/12 10:30:02  santtu
75   * Some typos, State -> MD5State etc.
76   *
77   * Revision 1.3  1996/04/15 07:28:09  santtu
78   * Added GPL statemets, and RSA derivate stametemetsnnts.
79   *
80   * Revision 1.2  1996/03/04 08:05:48  santtu
81   * Added offsets to Update method
82   *
83   * Revision 1.1  1996/01/07 20:51:59  santtu
84   * Initial revision
85   *
86   */
87  
88  /**
89   * Implementation of RSA's MD5 hash generator
90   *
91   * @version  $Revision: 1.3 $
92   * @author  Santeri Paavolainen <sjpaavol@cc.helsinki.fi>
93   */
94  
95  public class MD5 {
96      /**
97       * MD5 state
98       */
99      MD5State  state;
100     
101     /**
102      * If Final() has been called, finals is set to the current finals
103      * state. Any Update() causes this to be set to null.
104      */
105     MD5State   finals;
106     
107     /**
108      * Padding for Final()
109      */
110     static byte  padding[] = {
111         (byte) 0x80, 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, 0, 0,
113         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
114     };
115     
116     /**
117      * Initialize MD5 internal state (object can be reused just by
118      * calling Init() after every Final()
119      */
120     public synchronized void Init() {
121         state = new MD5.MD5State();
122         finals = null;
123     }
124     
125     /**
126      * Class constructor
127      */
128     public MD5() {
129         this.Init();
130     }
131     
132     /**
133      * Initialize class, and update hash with ob.toString()
134      *
135      * @param  ob  Object, ob.toString() is used to update hash
136      *      after initialization
137      */
138     public MD5(Object ob) {
139         this();
140         Update(ob.toString());
141     }
142     
143     private int rotate_left(int x, int n) {
144         return (x << n) | (x >>> (32 - n));
145     }
146     
147   /* I wonder how many loops and hoops you'll have to go through to
148      get unsigned add for longs in java */
149     
150     private int uadd(int a, int b) {
151         long aa, bb;
152         aa = ((long) a) & 0xffffffffL;
153         bb = ((long) b) & 0xffffffffL;
154         
155         aa += bb;
156         
157         return (int) (aa & 0xffffffffL);
158     }
159     
160     private int uadd(int a, int b, int c) {
161         return uadd(uadd(a, b), c);
162     }
163     
164     private int uadd(int a, int b, int c, int d) {
165         return uadd(uadd(a, b, c), d);
166     }
167     
168     private int FF(int a, int b, int c, int d, int x, int s, int ac) {
169         a = uadd(a, ((b & c) | (~b & d)), x, ac);
170         return uadd(rotate_left(a, s), b);
171     }
172     
173     private int GG(int a, int b, int c, int d, int x, int s, int ac) {
174         a = uadd(a, ((b & d) | (c & ~d)), x, ac);
175         return uadd(rotate_left(a, s), b);
176     }
177     
178     private int HH(int a, int b, int c, int d, int x, int s, int ac) {
179         a = uadd(a, (b ^ c ^ d), x, ac);
180         return uadd(rotate_left(a, s) , b);
181     }
182     
183     private int II(int a, int b, int c, int d, int x, int s, int ac) {
184         a = uadd(a, (c ^ (b | ~d)), x, ac);
185         return uadd(rotate_left(a, s), b);
186     }
187     
188     private int[] Decode(byte buffer[], int len, int shift) {
189         int    out[];
190         int   i, j;
191         
192         out = new int[16];
193         
194         for (i = j = 0; j < len; i++, j += 4) {
195             out[i] = ((int) (buffer[j + shift] & 0xff)) |
196             (((int) (buffer[j + 1 + shift] & 0xff)) << 8) |
197             (((int) (buffer[j + 2 + shift] & 0xff)) << 16) |
198             (((int) (buffer[j + 3 + shift] & 0xff)) << 24);
199             
200 /*      System.out.println("out[" + i + "] = \t" +
201                          ((int) buffer[j + 0 + shift] & 0xff) + "\t|\t" +
202                          ((int) buffer[j + 1 + shift] & 0xff) + "\t|\t" +
203                          ((int) buffer[j + 2 + shift] & 0xff) + "\t|\t" +
204                          ((int) buffer[j + 3 + shift] & 0xff));*/
205         }
206         
207         return out;
208     }
209     
210     private void Transform(MD5State state, byte buffer[], int shift) {
211         int
212         a = state.state[0],
213         b = state.state[1],
214         c = state.state[2],
215         d = state.state[3],
216         x[];
217         
218         x = Decode(buffer, 64, shift);
219         
220         /* Round 1 */
221         a = FF(a, b, c, d, x[ 0],   7, 0xd76aa478); /* 1 */
222         d = FF(d, a, b, c, x[ 1],  12, 0xe8c7b756); /* 2 */
223         c = FF(c, d, a, b, x[ 2],  17, 0x242070db); /* 3 */
224         b = FF(b, c, d, a, x[ 3],  22, 0xc1bdceee); /* 4 */
225         a = FF(a, b, c, d, x[ 4],   7, 0xf57c0faf); /* 5 */
226         d = FF(d, a, b, c, x[ 5],  12, 0x4787c62a); /* 6 */
227         c = FF(c, d, a, b, x[ 6],  17, 0xa8304613); /* 7 */
228         b = FF(b, c, d, a, x[ 7],  22, 0xfd469501); /* 8 */
229         a = FF(a, b, c, d, x[ 8],   7, 0x698098d8); /* 9 */
230         d = FF(d, a, b, c, x[ 9],  12, 0x8b44f7af); /* 10 */
231         c = FF(c, d, a, b, x[10],  17, 0xffff5bb1); /* 11 */
232         b = FF(b, c, d, a, x[11],  22, 0x895cd7be); /* 12 */
233         a = FF(a, b, c, d, x[12],   7, 0x6b901122); /* 13 */
234         d = FF(d, a, b, c, x[13],  12, 0xfd987193); /* 14 */
235         c = FF(c, d, a, b, x[14],  17, 0xa679438e); /* 15 */
236         b = FF(b, c, d, a, x[15],  22, 0x49b40821); /* 16 */
237         
238         /* Round 2 */
239         a = GG(a, b, c, d, x[ 1],   5, 0xf61e2562); /* 17 */
240         d = GG(d, a, b, c, x[ 6],   9, 0xc040b340); /* 18 */
241         c = GG(c, d, a, b, x[11],  14, 0x265e5a51); /* 19 */
242         b = GG(b, c, d, a, x[ 0],  20, 0xe9b6c7aa); /* 20 */
243         a = GG(a, b, c, d, x[ 5],   5, 0xd62f105d); /* 21 */
244         d = GG(d, a, b, c, x[10],   9,  0x2441453); /* 22 */
245         c = GG(c, d, a, b, x[15],  14, 0xd8a1e681); /* 23 */
246         b = GG(b, c, d, a, x[ 4],  20, 0xe7d3fbc8); /* 24 */
247         a = GG(a, b, c, d, x[ 9],   5, 0x21e1cde6); /* 25 */
248         d = GG(d, a, b, c, x[14],   9, 0xc33707d6); /* 26 */
249         c = GG(c, d, a, b, x[ 3],  14, 0xf4d50d87); /* 27 */
250         b = GG(b, c, d, a, x[ 8],  20, 0x455a14ed); /* 28 */
251         a = GG(a, b, c, d, x[13],   5, 0xa9e3e905); /* 29 */
252         d = GG(d, a, b, c, x[ 2],   9, 0xfcefa3f8); /* 30 */
253         c = GG(c, d, a, b, x[ 7],  14, 0x676f02d9); /* 31 */
254         b = GG(b, c, d, a, x[12],  20, 0x8d2a4c8a); /* 32 */
255         
256         /* Round 3 */
257         a = HH(a, b, c, d, x[ 5],   4, 0xfffa3942); /* 33 */
258         d = HH(d, a, b, c, x[ 8],  11, 0x8771f681); /* 34 */
259         c = HH(c, d, a, b, x[11],  16, 0x6d9d6122); /* 35 */
260         b = HH(b, c, d, a, x[14],  23, 0xfde5380c); /* 36 */
261         a = HH(a, b, c, d, x[ 1],   4, 0xa4beea44); /* 37 */
262         d = HH(d, a, b, c, x[ 4],  11, 0x4bdecfa9); /* 38 */
263         c = HH(c, d, a, b, x[ 7],  16, 0xf6bb4b60); /* 39 */
264         b = HH(b, c, d, a, x[10],  23, 0xbebfbc70); /* 40 */
265         a = HH(a, b, c, d, x[13],   4, 0x289b7ec6); /* 41 */
266         d = HH(d, a, b, c, x[ 0],  11, 0xeaa127fa); /* 42 */
267         c = HH(c, d, a, b, x[ 3],  16, 0xd4ef3085); /* 43 */
268         b = HH(b, c, d, a, x[ 6],  23,  0x4881d05); /* 44 */
269         a = HH(a, b, c, d, x[ 9],   4, 0xd9d4d039); /* 45 */
270         d = HH(d, a, b, c, x[12],  11, 0xe6db99e5); /* 46 */
271         c = HH(c, d, a, b, x[15],  16, 0x1fa27cf8); /* 47 */
272         b = HH(b, c, d, a, x[ 2],  23, 0xc4ac5665); /* 48 */
273         
274         /* Round 4 */
275         a = II(a, b, c, d, x[ 0],   6, 0xf4292244); /* 49 */
276         d = II(d, a, b, c, x[ 7],  10, 0x432aff97); /* 50 */
277         c = II(c, d, a, b, x[14],  15, 0xab9423a7); /* 51 */
278         b = II(b, c, d, a, x[ 5],  21, 0xfc93a039); /* 52 */
279         a = II(a, b, c, d, x[12],   6, 0x655b59c3); /* 53 */
280         d = II(d, a, b, c, x[ 3],  10, 0x8f0ccc92); /* 54 */
281         c = II(c, d, a, b, x[10],  15, 0xffeff47d); /* 55 */
282         b = II(b, c, d, a, x[ 1],  21, 0x85845dd1); /* 56 */
283         a = II(a, b, c, d, x[ 8],   6, 0x6fa87e4f); /* 57 */
284         d = II(d, a, b, c, x[15],  10, 0xfe2ce6e0); /* 58 */
285         c = II(c, d, a, b, x[ 6],  15, 0xa3014314); /* 59 */
286         b = II(b, c, d, a, x[13],  21, 0x4e0811a1); /* 60 */
287         a = II(a, b, c, d, x[ 4],   6, 0xf7537e82); /* 61 */
288         d = II(d, a, b, c, x[11],  10, 0xbd3af235); /* 62 */
289         c = II(c, d, a, b, x[ 2],  15, 0x2ad7d2bb); /* 63 */
290         b = II(b, c, d, a, x[ 9],  21, 0xeb86d391); /* 64 */
291         
292         state.state[0] += a;
293         state.state[1] += b;
294         state.state[2] += c;
295         state.state[3] += d;
296     }
297     
298     /**
299      * Updates hash with the bytebuffer given (using at maximum length bytes from
300      * that buffer)
301      *
302      * @param state  Which state is updated
303      * @param buffer  Array of bytes to be hashed
304      * @param offset  Offset to buffer array
305      * @param length  Use at maximum `length' bytes (absolute
306      *      maximum is buffer.length)
307      */
308     public void Update(MD5State stat, byte buffer[], int offset, int length) {
309         int  index, partlen, i, start;
310         
311 /*    System.out.print("Offset = " + offset + "\tLength = " + length + "\t");
312     System.out.print("Buffer = ");
313     for (i = 0; i < buffer.length; i++)
314         System.out.print((int) (buffer[i] & 0xff) + " ");
315     System.out.print("\n");*/
316         
317         finals = null;
318         
319         /* Length can be told to be shorter, but not inter */
320         if ((length - offset)> buffer.length)
321             length = buffer.length - offset;
322         
323         /* compute number of bytes mod 64 */
324         index = (int) (stat.count[0] >>> 3) & 0x3f;
325         
326         if ((stat.count[0] += (length << 3)) <
327         (length << 3))
328             stat.count[1]++;
329         
330         stat.count[1] += length >>> 29;
331         
332         partlen = 64 - index;
333         
334         if (length >= partlen) {
335             for (i = 0; i < partlen; i++)
336                 stat.buffer[i + index] = buffer[i + offset];
337             
338             Transform(stat, stat.buffer, 0);
339             
340             for (i = partlen; (i + 63) < length; i+= 64)
341                 Transform(stat, buffer, i);
342             
343             index = 0;
344         } else
345             i = 0;
346         
347         /* buffer remaining input */
348         if (i < length) {
349             start = i;
350             for (; i < length; i++)
351                 stat.buffer[index + i - start] = buffer[i + offset];
352         }
353     }
354     
355   /*
356    * Update()s for other datatypes than byte[] also. Update(byte[], int)
357    * is only the main driver.
358    */
359     
360     /**
361      * Plain update, updates this object
362      */
363     
364     public void Update(byte buffer[], int offset, int length) {
365         Update(this.state, buffer, offset, length);
366     }
367     
368     public void Update(byte buffer[], int length) {
369         Update(this.state, buffer, 0, length);
370     }
371     
372     /**
373      * Updates hash with given array of bytes
374      *
375      * @param buffer  Array of bytes to use for updating the hash
376      */
377     public void Update(byte buffer[]) {
378         Update(buffer, 0, buffer.length);
379     }
380     
381     /**
382      * Updates hash with a single byte
383      *
384      * @param b    Single byte to update the hash
385      */
386     public void Update(byte b) {
387         byte buffer[] = new byte[1];
388         buffer[0] = b;
389         
390         Update(buffer, 1);
391     }
392     
393     /**
394      * Update buffer with given string.
395      *
396      * @param s    String to be update to hash (is used as
397      *             s.getBytes())
398      */
399     public void Update(String s) {
400         byte  chars[];
401         
402         chars = new byte[s.length()];
403         // tobias
404         chars = s.getBytes();
405         //    s.getBytes(0, s.length(), chars, 0);
406         
407         Update(chars, chars.length);
408     }
409     
410     /**
411      * Update buffer with a single integer (only & 0xff part is used,
412      * as a byte)
413      *
414      * @param i    Integer value, which is then converted to
415      *      byte as i & 0xff
416      */
417     
418     public void Update(int i) {
419         Update((byte) (i & 0xff));
420     }
421     
422     private byte[] Encode(int input[], int len) {
423         int    i, j;
424         byte  out[];
425         
426         out = new byte[len];
427         
428         for (i = j = 0; j  < len; i++, j += 4) {
429             out[j] = (byte) (input[i] & 0xff);
430             out[j + 1] = (byte) ((input[i] >>> 8) & 0xff);
431             out[j + 2] = (byte) ((input[i] >>> 16) & 0xff);
432             out[j + 3] = (byte) ((input[i] >>> 24) & 0xff);
433         }
434         
435         return out;
436     }
437     
438     /**
439      * Returns array of bytes (16 bytes) representing hash as of the
440      * current state of this object. Note: getting a hash does not
441      * invalidate the hash object, it only creates a copy of the real
442      * state which is finalized.
443      *
444      * @return  Array of 16 bytes, the hash of all updated bytes
445      */
446     public synchronized byte[] Final() {
447         byte  bits[];
448         int    index, padlen;
449         MD5State  fin;
450         
451         if (finals == null) {
452             fin = new MD5.MD5State(state);
453             
454             bits = Encode(fin.count, 8);
455             
456             index = (int) ((fin.count[0] >>> 3) & 0x3f);
457             padlen = (index < 56) ? (56 - index) : (120 - index);
458             
459             Update(fin, padding, 0, padlen);
460             /**/
461             Update(fin, bits, 0, 8);
462             
463             /* Update() sets finalds to null */
464             finals = fin;
465         }
466         
467         return Encode(finals.state, 16);
468     }
469     
470     /**
471      * Turns array of bytes into string representing each byte as
472      * unsigned hex number.
473      *
474      * @param hash  Array of bytes to convert to hex-string
475      * @return  Generated hex string
476      */
477     public static String asHex(byte hash[]) {
478         StringBuffer buf = new StringBuffer(hash.length * 2);
479         int i;
480         
481         for (i = 0; i < hash.length; i++) {
482             if (((int) hash[i] & 0xff) < 0x10)
483                 buf.append("0");
484             
485             buf.append(Long.toString((int) hash[i] & 0xff, 16));
486         }
487         
488         return buf.toString();
489     }
490     
491     /**
492      * Returns 32-character hex representation of this objects hash
493      *
494      * @return String of this object's hash
495      */
496     public String asHex() {
497         return asHex(this.Final());
498     }
499     
500     /**
501      * Contains internal state of the MD5 class
502      */
503     private class MD5State {
504         /**
505          * 128-byte state
506          */
507         int  state[];
508         
509         /**
510          * 64-bit character count (could be true Java long?)
511          */
512         int  count[];
513         
514         /**
515          * 64-byte buffer (512 bits) for storing to-be-hashed characters
516          */
517         byte  buffer[];
518         
519         public MD5State() {
520             buffer = new byte[64];
521             count = new int[2];
522             state = new int[4];
523             
524             state[0] = 0x67452301;
525             state[1] = 0xefcdab89;
526             state[2] = 0x98badcfe;
527             state[3] = 0x10325476;
528             
529             count[0] = count[1] = 0;
530         }
531         
532         /** Create this State as a copy of another state */
533         public MD5State(MD5State from) {
534             this();
535             
536             int i;
537             
538             for (i = 0; i < buffer.length; i++)
539                 this.buffer[i] = from.buffer[i];
540             
541             for (i = 0; i < state.length; i++)
542                 this.state[i] = from.state[i];
543             
544             for (i = 0; i < count.length; i++)
545                 this.count[i] = from.count[i];
546         }
547     };
548 }