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