001: package org.apache.java.security;
002:
003: /*
004: * Copyright 2001-2005 The Apache Software Foundation.
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License")
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: /**
020: * This class implements the Message Digest 5 algorithm (MD5) as
021: * defined in RFC-1321.
022: *
023: * <p><b>Note:</b> even if standard Java 1.1 APIs already provide a
024: * MD5 implementation, this class is used on those Java runtime
025: * environments (like Kaffe) where the package
026: * <code>java.security</code> is highly improbable to be found.
027: *
028: * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
029: * @version $Id: MD5.java 264148 2005-08-29 14:21:04Z henning $
030: * @deprecated Use the java.security package.
031: */
032: public final class MD5 extends MessageDigest {
033: private long counter;
034: private int reminder;
035: private byte buffer[];
036: private int state[];
037: private int x[];
038:
039: /*********************** MD5 Functions ***********************/
040:
041: // 16 * 4 bytes
042: static byte padding[] = { (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0,
043: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
044: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
045: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
046:
047: /*********************** Self Test ***********************/
048:
049: private static String[] messages = {
050: "",
051: "a",
052: "abc",
053: "message digest",
054: "abcdefghijklmnopqrstuvwxyz",
055: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
056: "12345678901234567890123456789012345678901234567890123456789012345678901234567890", };
057:
058: private static String[] digests = {
059: "d41d8cd98f00b204e9800998ecf8427e",
060: "0cc175b9c0f1b6a831c399e269772661",
061: "900150983cd24fb0d6963f7d28e17f72",
062: "f96b697d7cb7938d525a2f31aaf161d0",
063: "c3fcd3d76192e4007dfb496cca67e13b",
064: "d174ab98d277d9f5a5611c2c9f419d9f",
065: "57edf4a22be3c955ac49da2e2107b67a", };
066:
067: /**
068: * Creates the algorithm and reset its state.
069: */
070: public MD5() {
071: super ();
072: }
073:
074: /**
075: * Append another block of specified length to the message
076: * starting at the given offset.
077: *
078: * @param block A byte[].
079: * @param offset An int.
080: * @param length An int.
081: */
082: public void append(byte[] block, int offset, int length) {
083: while (true) {
084: if (length >= reminder) {
085: System.arraycopy(block, offset, buffer,
086: (int) (counter & 63L), reminder);
087: transform(buffer);
088: counter += reminder;
089: offset += reminder;
090: length -= reminder;
091: reminder = 64;
092: } else {
093: System.arraycopy(block, offset, buffer,
094: (int) (counter & 63L), length);
095: counter += length;
096: reminder -= length;
097: break;
098: }
099: }
100: }
101:
102: /*********************** Byte/Int utilities ***********************/
103:
104: /**
105: * Converts a 64-byte array into a 16-int array.
106: *
107: * @param in A byte[].
108: * @param out An int[].
109: */
110: private static void byte2int(byte[] in, int[] out) {
111: for (int inpos = 0, outpos = 0; outpos < 16; outpos++) {
112: out[outpos] = ((((int) (in[inpos++] & 0xff)))
113: | (((int) (in[inpos++] & 0xff)) << 8)
114: | (((int) (in[inpos++] & 0xff)) << 16) | (((int) (in[inpos++] & 0xff)) << 24));
115: }
116: }
117:
118: /**
119: * Appends a message block with specified length starting from the
120: * given offset, and return its message digest.
121: *
122: * @param block A byte[].
123: * @param offset An int.
124: * @param length An int.
125: */
126: public byte[] digest(byte[] block, int offset, int length) {
127: this .append(block, offset, length);
128:
129: byte[] bits = toBytes(counter << 3);
130: byte[] digest = new byte[16];
131:
132: if (reminder > 8) {
133: append(padding, 0, reminder - 8);
134: } else {
135: append(padding, 0, 64 + (reminder - 8));
136: }
137:
138: append(bits, 0, 8);
139:
140: int2byte(state, digest);
141:
142: this .reset();
143: return digest;
144: }
145:
146: /*
147: * Method F.
148: *
149: * @param x An int.
150: * @param y An int.
151: * @param z An int.
152: * @return An int.
153: */
154: static private int F(int x, int y, int z) {
155: return (z ^ (x & (y ^ z)));
156: }
157:
158: /*
159: * Method FF.
160: *
161: * @param a An int.
162: * @param b An int.
163: * @param c An int.
164: * @param d An int.
165: * @param x An int.
166: * @param s An int.
167: * @param ac An int.
168: * @return An int.
169: */
170: static private int FF(int a, int b, int c, int d, int x, int s,
171: int ac) {
172: a += x + ac + F(b, c, d);
173: a = (a << s | a >>> -s);
174: return a + b;
175: }
176:
177: /*
178: * Method G.
179: *
180: * @param x An int.
181: * @param y An int.
182: * @param z An int.
183: * @return An int.
184: */
185: static private int G(int x, int y, int z) {
186: return (y ^ (z & (x ^ y)));
187: }
188:
189: /*
190: * Method GG.
191: *
192: * @param a An int.
193: * @param b An int.
194: * @param c An int.
195: * @param d An int.
196: * @param x An int.
197: * @param s An int.
198: * @param ac An int.
199: * @return An int.
200: */
201: static private int GG(int a, int b, int c, int d, int x, int s,
202: int ac) {
203: a += x + ac + G(b, c, d);
204: a = (a << s | a >>> -s);
205: return a + b;
206: }
207:
208: /*
209: * Method H.
210: *
211: * @param x An int.
212: * @param y An int.
213: * @param z An int.
214: * @return An int.
215: */
216: static private int H(int x, int y, int z) {
217: return (x ^ y ^ z);
218: }
219:
220: /*
221: * Method HH.
222: *
223: * @param a An int.
224: * @param b An int.
225: * @param c An int.
226: * @param d An int.
227: * @param x An int.
228: * @param s An int.
229: * @param ac An int.
230: * @return An int.
231: */
232: static private int HH(int a, int b, int c, int d, int x, int s,
233: int ac) {
234: a += x + ac + H(b, c, d);
235: a = (a << s | a >>> -s);
236: return a + b;
237: }
238:
239: /*
240: * Method I.
241: *
242: * @param x An int.
243: * @param y An int.
244: * @param z An int.
245: * @return An int.
246: */
247: static private int I(int x, int y, int z) {
248: return (y ^ (x | ~z));
249: }
250:
251: /*
252: * Method II.
253: *
254: * @param a An int.
255: * @param b An int.
256: * @param c An int.
257: * @param d An int.
258: * @param x An int.
259: * @param s An int.
260: * @param ac An int.
261: * @return An int.
262: */
263: static private int II(int a, int b, int c, int d, int x, int s,
264: int ac) {
265: a += x + ac + I(b, c, d);
266: a = (a << s | a >>> -s);
267: return a + b;
268: }
269:
270: /**
271: * Converts a 4-int array into a 16-byte array.
272: *
273: * @param in An int[].
274: * @param out A byte[].
275: */
276: private static void int2byte(int[] in, byte[] out) {
277: for (int inpos = 0, outpos = 0; inpos < 4; inpos++) {
278: out[outpos++] = (byte) (in[inpos] & 0xff);
279: out[outpos++] = (byte) ((in[inpos] >>> 8) & 0xff);
280: out[outpos++] = (byte) ((in[inpos] >>> 16) & 0xff);
281: out[outpos++] = (byte) ((in[inpos] >>> 24) & 0xff);
282: }
283: }
284:
285: /*
286: * Main routine, for testing purposes only.
287: *
288: * @param ignored A String[] with the command line arguments.
289: */
290: public static final void main(String[] ignored) {
291: MD5 md5 = new MD5();
292:
293: for (int i = 0; i < messages.length; i++) {
294: String digest = org.apache.java.lang.Bytes.toString(md5
295: .digest(messages[i].getBytes()));
296: System.out.println("Computed: " + digest);
297: System.out.println("Correct: " + digests[i]);
298: if (digest.equalsIgnoreCase(digests[i])) {
299: System.out.println("Test " + i + " passed.");
300: } else {
301: System.out.println("Test " + i + " failed.");
302: }
303: }
304: }
305:
306: /**
307: * Resets the state of the class. <b>Beware</b>: calling this
308: * method erases all data previously inserted.
309: */
310: public void reset() {
311: buffer = new byte[64];
312: state = new int[4];
313: x = new int[16];
314:
315: state[0] = 0x67452301;
316: state[1] = 0xefcdab89;
317: state[2] = 0x98badcfe;
318: state[3] = 0x10325476;
319:
320: counter = 0;
321: reminder = 64;
322: }
323:
324: /**
325: * Converts a long to a 8-byte array using low order first.
326: *
327: * @param n A long.
328: * @return A byte[].
329: */
330: public static byte[] toBytes(long n) {
331: byte[] b = new byte[8];
332:
333: b[0] = (byte) (n);
334: n >>>= 8;
335: b[1] = (byte) (n);
336: n >>>= 8;
337: b[2] = (byte) (n);
338: n >>>= 8;
339: b[3] = (byte) (n);
340: n >>>= 8;
341: b[4] = (byte) (n);
342: n >>>= 8;
343: b[5] = (byte) (n);
344: n >>>= 8;
345: b[6] = (byte) (n);
346: n >>>= 8;
347: b[7] = (byte) (n);
348:
349: return b;
350: }
351:
352: /*
353: * TODO: Document.
354: *
355: * @param buffer A byte[].
356: */
357: private void transform(byte[] buffer) {
358: int a, b, c, d;
359:
360: byte2int(buffer, x);
361:
362: a = state[0];
363: b = state[1];
364: c = state[2];
365: d = state[3];
366:
367: a = FF(a, b, c, d, x[0], 7, 0xd76aa478);
368: d = FF(d, a, b, c, x[1], 12, 0xe8c7b756);
369: c = FF(c, d, a, b, x[2], 17, 0x242070db);
370: b = FF(b, c, d, a, x[3], 22, 0xc1bdceee);
371: a = FF(a, b, c, d, x[4], 7, 0xf57c0faf);
372: d = FF(d, a, b, c, x[5], 12, 0x4787c62a);
373: c = FF(c, d, a, b, x[6], 17, 0xa8304613);
374: b = FF(b, c, d, a, x[7], 22, 0xfd469501);
375: a = FF(a, b, c, d, x[8], 7, 0x698098d8);
376: d = FF(d, a, b, c, x[9], 12, 0x8b44f7af);
377: c = FF(c, d, a, b, x[10], 17, 0xffff5bb1);
378: b = FF(b, c, d, a, x[11], 22, 0x895cd7be);
379: a = FF(a, b, c, d, x[12], 7, 0x6b901122);
380: d = FF(d, a, b, c, x[13], 12, 0xfd987193);
381: c = FF(c, d, a, b, x[14], 17, 0xa679438e);
382: b = FF(b, c, d, a, x[15], 22, 0x49b40821);
383:
384: a = GG(a, b, c, d, x[1], 5, 0xf61e2562);
385: d = GG(d, a, b, c, x[6], 9, 0xc040b340);
386: c = GG(c, d, a, b, x[11], 14, 0x265e5a51);
387: b = GG(b, c, d, a, x[0], 20, 0xe9b6c7aa);
388: a = GG(a, b, c, d, x[5], 5, 0xd62f105d);
389: d = GG(d, a, b, c, x[10], 9, 0x2441453);
390: c = GG(c, d, a, b, x[15], 14, 0xd8a1e681);
391: b = GG(b, c, d, a, x[4], 20, 0xe7d3fbc8);
392: a = GG(a, b, c, d, x[9], 5, 0x21e1cde6);
393: d = GG(d, a, b, c, x[14], 9, 0xc33707d6);
394: c = GG(c, d, a, b, x[3], 14, 0xf4d50d87);
395: b = GG(b, c, d, a, x[8], 20, 0x455a14ed);
396: a = GG(a, b, c, d, x[13], 5, 0xa9e3e905);
397: d = GG(d, a, b, c, x[2], 9, 0xfcefa3f8);
398: c = GG(c, d, a, b, x[7], 14, 0x676f02d9);
399: b = GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);
400:
401: a = HH(a, b, c, d, x[5], 4, 0xfffa3942);
402: d = HH(d, a, b, c, x[8], 11, 0x8771f681);
403: c = HH(c, d, a, b, x[11], 16, 0x6d9d6122);
404: b = HH(b, c, d, a, x[14], 23, 0xfde5380c);
405: a = HH(a, b, c, d, x[1], 4, 0xa4beea44);
406: d = HH(d, a, b, c, x[4], 11, 0x4bdecfa9);
407: c = HH(c, d, a, b, x[7], 16, 0xf6bb4b60);
408: b = HH(b, c, d, a, x[10], 23, 0xbebfbc70);
409: a = HH(a, b, c, d, x[13], 4, 0x289b7ec6);
410: d = HH(d, a, b, c, x[0], 11, 0xeaa127fa);
411: c = HH(c, d, a, b, x[3], 16, 0xd4ef3085);
412: b = HH(b, c, d, a, x[6], 23, 0x4881d05);
413: a = HH(a, b, c, d, x[9], 4, 0xd9d4d039);
414: d = HH(d, a, b, c, x[12], 11, 0xe6db99e5);
415: c = HH(c, d, a, b, x[15], 16, 0x1fa27cf8);
416: b = HH(b, c, d, a, x[2], 23, 0xc4ac5665);
417:
418: a = II(a, b, c, d, x[0], 6, 0xf4292244);
419: d = II(d, a, b, c, x[7], 10, 0x432aff97);
420: c = II(c, d, a, b, x[14], 15, 0xab9423a7);
421: b = II(b, c, d, a, x[5], 21, 0xfc93a039);
422: a = II(a, b, c, d, x[12], 6, 0x655b59c3);
423: d = II(d, a, b, c, x[3], 10, 0x8f0ccc92);
424: c = II(c, d, a, b, x[10], 15, 0xffeff47d);
425: b = II(b, c, d, a, x[1], 21, 0x85845dd1);
426: a = II(a, b, c, d, x[8], 6, 0x6fa87e4f);
427: d = II(d, a, b, c, x[15], 10, 0xfe2ce6e0);
428: c = II(c, d, a, b, x[6], 15, 0xa3014314);
429: b = II(b, c, d, a, x[13], 21, 0x4e0811a1);
430: a = II(a, b, c, d, x[4], 6, 0xf7537e82);
431: d = II(d, a, b, c, x[11], 10, 0xbd3af235);
432: c = II(c, d, a, b, x[2], 15, 0x2ad7d2bb);
433: b = II(b, c, d, a, x[9], 21, 0xeb86d391);
434:
435: state[0] += a;
436: state[1] += b;
437: state[2] += c;
438: state[3] += d;
439: }
440: }
|