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