001: /*
002: * $Id: MD5.java,v 1.1 2003/03/27 11:16:08 bs126381 Exp $
003: *
004: * Implements the MD5 hashing algorithm.
005: *
006: * $Log: MD5.java,v $
007: * Revision 1.1 2003/03/27 11:16:08 bs126381
008: * Netlet on SSL, SunRay
009: *
010: * Revision 1.1.2.1 2003/01/27 09:51:36 bs126381
011: * Netlet on SSL
012: *
013: * Revision 1.2 2000/03/31 02:24:21 vgupta
014: * Modified reset() to zero out buffer.
015: *
016: * Revision 1.1 2000/03/29 02:51:15 vgupta
017: * Initial revision
018: *
019: */
020:
021: // package javacard.security;
022: package com.sun.portal.ksecurity;
023:
024: final class MD5 extends MessageDigest {
025: /** Indicates the MD5 message digest algorithm. */
026: public static final byte ALG_MD5 = 1;
027: /** Indicates the SHA message digest algorithm. */
028: public static final byte ALG_SHA = 2;
029:
030: private static final int S11 = 7;
031: private static final int S12 = 12;
032: private static final int S13 = 17;
033: private static final int S14 = 22;
034: private static final int S21 = 5;
035: private static final int S22 = 9;
036: private static final int S23 = 14;
037: private static final int S24 = 20;
038: private static final int S31 = 4;
039: private static final int S32 = 11;
040: private static final int S33 = 16;
041: private static final int S34 = 23;
042: private static final int S41 = 6;
043: private static final int S42 = 10;
044: private static final int S43 = 15;
045: private static final int S44 = 21;
046:
047: private static final byte[] padding = { (byte) 0x80, (byte) 0x00,
048: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
049: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
050: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
051: (byte) 0x00, (byte) 0x00,
052:
053: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
054: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
055: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
056: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
057:
058: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
059: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
060: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
061: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
062:
063: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
064: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
065: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
066: (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, };
067:
068: /* Internal context */
069: // state: A, B, C, D
070: private int[] state = new int[4];
071: // number of bits modulo 2^64 (LSB first)
072: private int[] count = new int[2];
073: // input buffer
074: private byte[] buffer = new byte[64];
075:
076: private byte type; // message digest algorithm
077: private byte len; // length of hash in bytes
078:
079: /*
080: * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
081: * Rotation is separate from addition to prevent recomputation.
082: */
083:
084: private static int FF(int a, int b, int c, int d, int x, int s,
085: int ac) {
086: int temp = 0;
087:
088: temp = ((b & c) | (~b & d));
089: a += temp + x + ac;
090: a = ((a << s) | (a >>> (32 - s)));
091: a += b;
092: return a;
093: }
094:
095: private static int GG(int a, int b, int c, int d, int x, int s,
096: int ac) {
097: int temp = 0;
098:
099: temp = (b & d) | (c & ~d);
100: a += temp + x + ac;
101: a = ((a << s) | (a >>> (32 - s)));
102: a += b;
103: return a;
104: }
105:
106: private static int HH(int a, int b, int c, int d, int x, int s,
107: int ac) {
108: int temp = 0;
109:
110: temp = (b ^ c ^ d);
111: a += temp + x + ac;
112: a = ((a << s) | (a >>> (32 - s)));
113: a += b;
114: return a;
115: }
116:
117: private static int II(int a, int b, int c, int d, int x, int s,
118: int ac) {
119: int temp = 0;
120:
121: temp = (c ^ (b | ~d));
122: a += temp + x + ac;
123: a = ((a << s) | (a >>> (32 - s)));
124: a += b;
125: return a;
126: }
127:
128: /*
129: * MD5 basic transformation. Transforms state based on a 64-byte block.
130: */
131: private void transform(byte[] block, int offset) {
132: int a = state[0];
133: int b = state[1];
134: int c = state[2];
135: int d = state[3];
136: int[] x = new int[16];
137:
138: for (int i = 0, j = offset; j < offset + 64; i++, j += 4) {
139: x[i] = (block[j] & 0xff) | ((block[j + 1] & 0xff) << 8)
140: | ((block[j + 2] & 0xff) << 16)
141: | ((block[j + 3] & 0xff) << 24);
142: }
143:
144: /* Round 1 */
145: a = FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
146: d = FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
147: c = FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
148: b = FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
149: a = FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
150: d = FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
151: c = FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
152: b = FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
153: a = FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
154: d = FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
155: c = FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
156: b = FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
157: a = FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
158: d = FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
159: c = FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
160: b = FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
161:
162: /* Round 2 */
163: a = GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
164: d = GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
165: c = GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
166: b = GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
167: a = GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
168: d = GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
169: c = GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
170: b = GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
171: a = GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
172: d = GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
173: c = GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
174: b = GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
175: a = GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
176: d = GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
177: c = GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
178: b = GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
179:
180: /* Round 3 */
181: a = HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
182: d = HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
183: c = HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
184: b = HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
185: a = HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
186: d = HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
187: c = HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
188: b = HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
189: a = HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
190: d = HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
191: c = HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
192: b = HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
193: a = HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
194: d = HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
195: c = HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
196: b = HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
197:
198: /* Round 4 */
199: a = II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
200: d = II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
201: c = II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
202: b = II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
203: a = II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
204: d = II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
205: c = II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
206: b = II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
207: a = II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
208: d = II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
209: c = II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
210: b = II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
211: a = II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
212: d = II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
213: c = II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
214: b = II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
215:
216: state[0] += a;
217: state[1] += b;
218: state[2] += c;
219: state[3] += d;
220:
221: // Zeroize sensitive information.
222: for (int i = 0; i < x.length; i++)
223: x[i] = 0;
224: }
225:
226: /*
227: * MD5 finalization. Ends an MD5 message-digest operation, writing the
228: * the message digest and zeroizing the context.
229: */
230: private byte[] digest() {
231: byte[] digest = new byte[16];
232: byte[] bits = new byte[8];
233: int index, padLen;
234:
235: // Save number of bits
236: bits[0] = (byte) (count[0] & 0xff);
237: bits[1] = (byte) ((count[0] >>> 8) & 0xff);
238: bits[2] = (byte) ((count[0] >>> 16) & 0xff);
239: bits[3] = (byte) ((count[0] >>> 24) & 0xff);
240:
241: bits[4] = (byte) (count[1] & 0xff);
242: bits[5] = (byte) ((count[1] >>> 8) & 0xff);
243: bits[6] = (byte) ((count[1] >>> 16) & 0xff);
244: bits[7] = (byte) ((count[1] >>> 24) & 0xff);
245:
246: // Pad out to 56 mod 64.
247: index = (count[0] >>> 3) & 0x3f;
248: padLen = (index < 56) ? (56 - index) : (120 - index);
249: update(padding, (short) 0, (short) padLen);
250:
251: // Append length (before padding)
252: update(bits, (short) 0, (short) 8);
253:
254: // Store state in digest
255: digest[0] = (byte) (state[0] & 0xff);
256: digest[1] = (byte) ((state[0] >>> 8) & 0xff);
257: digest[2] = (byte) ((state[0] >>> 16) & 0xff);
258: digest[3] = (byte) ((state[0] >>> 24) & 0xff);
259:
260: digest[4] = (byte) (state[1] & 0xff);
261: digest[5] = (byte) ((state[1] >>> 8) & 0xff);
262: digest[6] = (byte) ((state[1] >>> 16) & 0xff);
263: digest[7] = (byte) ((state[1] >>> 24) & 0xff);
264:
265: digest[8] = (byte) (state[2] & 0xff);
266: digest[9] = (byte) ((state[2] >>> 8) & 0xff);
267: digest[10] = (byte) ((state[2] >>> 16) & 0xff);
268: digest[11] = (byte) ((state[2] >>> 24) & 0xff);
269:
270: digest[12] = (byte) (state[3] & 0xff);
271: digest[13] = (byte) ((state[3] >>> 8) & 0xff);
272: digest[14] = (byte) ((state[3] >>> 16) & 0xff);
273: digest[15] = (byte) ((state[3] >>> 24) & 0xff);
274:
275: // Zeroize sensitive information
276: count[0] = count[1] = 0;
277: state[0] = state[1] = state[2] = state[3] = 0;
278:
279: return (digest);
280: }
281:
282: MD5() {
283: type = ALG_MD5;
284: len = 16;
285: reset();
286: }
287:
288: public byte getAlgorithm() {
289: return type;
290: }
291:
292: public byte getLength() {
293: return len;
294: }
295:
296: /* MD5 initialization. Begins an MD5 operation, writing a new context */
297: public void reset() {
298: count[0] = 0;
299: count[1] = 0;
300:
301: // Load magic initialization constants.
302: state[0] = 0x67452301;
303: state[1] = 0xefcdab89;
304: state[2] = 0x98badcfe;
305: state[3] = 0x10325476;
306:
307: type = ALG_MD5;
308: len = 16;
309: for (int i = 0; i < 64; i++)
310: buffer[i] = (byte) 0;
311: }
312:
313: /*
314: * MD5 block update operation. Continues an MD5 message-digest
315: * operation, processing another message block, and updating internal
316: * context.
317: */
318: public void update(byte[] input, int offset, int len) {
319: int i = 0;
320: int index = 0;
321: int partLen = 0;
322: if (input == null)
323: return;
324: // Compute number of bytes mod 64
325: index = (count[0] >>> 3) & 0x3F;
326: // Update number of bits
327: /* TODO: We have a problem here because int is signed */
328: count[0] += (len << 3);
329: if (count[0] < (len << 3)) {
330: count[1]++;
331: }
332: count[1] += (len >>> 29);
333:
334: partLen = 64 - index;
335: if (len >= partLen) {
336: System.arraycopy(input, offset, buffer, index, partLen);
337: transform(buffer, 0);
338:
339: for (i = partLen; (i + 63) < len; i += 64) {
340: transform(input, i + offset);
341: }
342:
343: index = 0;
344: } else {
345: i = 0;
346: }
347: System.arraycopy(input, i + offset, buffer, index, len - i);
348: }
349:
350: public short doFinal(byte[] inBuf, int inOff, int inLen,
351: byte[] outBuf, int outOff) {
352: // check the parameters to prevent a VM crash
353: int cnt = outBuf[outOff] + outBuf[outOff + this .len - 1];
354:
355: this .update(inBuf, inOff, inLen);
356: cnt = (outBuf.length > outOff) ? (outBuf.length - outOff) : 0;
357: // if (cnt == 0) return ((short) 0);
358: if (this .len < cnt)
359: cnt = this .len;
360: System.arraycopy(this .digest(), 0, outBuf, outOff, cnt);
361: reset();
362: return ((short) cnt);
363: }
364:
365: public Object clone() {
366: MD5 cpy = new MD5();
367:
368: System.arraycopy(this .state, 0, cpy.state, 0, 4);
369: System.arraycopy(this .buffer, 0, cpy.buffer, 0, 64);
370: System.arraycopy(this .count, 0, cpy.count, 0, 2);
371: cpy.type = this.type;
372: cpy.len = this.len;
373: return cpy;
374: }
375: }
|