001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.crypto;
028:
029: /**
030: * Implements the MD5 hashing algorithm as described in IETF RFC 1321
031: * (see http://www.ietf.org/rfc/rfc1321.txt)
032: */
033: final class MD5 extends MessageDigest {
034: /*
035: * The compute intensive operations are implemented in C
036: * based on the OpenSSL MD5 code (from pilotSSLeay). Here we
037: * replicate the state the C code needs.
038: */
039:
040: /** State needed for MD5 hash, four elements correspond to A, B, C, D. */
041: private int[] state = new int[4];
042: /** State needed for MD5 hash. */
043: private int[] num = new int[1];
044: /** Number of bits modulo 2^64 (LSB first) */
045: private int[] count = new int[2];
046: /** Input data. */
047: private int[] data = new int[16];
048:
049: /** Create an MD5 digest object. */
050: MD5() {
051: reset();
052: }
053:
054: /**
055: * Gets the message digest algorithm.
056: * @return algorithm implemented by this MessageDigest object
057: */
058: public String getAlgorithm() {
059: return "MD5";
060: }
061:
062: /**
063: * Gets the length (in bytes) of the hash.
064: * @return byte-length of the hash produced by this object
065: */
066: public int getDigestLength() {
067: return 16;
068: }
069:
070: /**
071: * Resets the MessageDigest to the initial state for further use.
072: */
073: public void reset() {
074: count[0] = 0;
075: count[1] = 0;
076:
077: // Load magic initialization constants.
078: state[0] = 0x67452301;
079: state[1] = 0xefcdab89;
080: state[2] = 0x98badcfe;
081: state[3] = 0x10325476;
082:
083: for (int i = 0; i < 16; i++)
084: data[i] = 0;
085:
086: num[0] = 0;
087: }
088:
089: /**
090: * Accumulates a hash of the input data. Continues an MD5
091: * message-digest operation, processing another message
092: * block, and updating the internal context.
093: * @param inBuf input buffer of data to be hashed
094: * @param inOff offset within inBuf where input data begins
095: * @param inLen length (in bytes) of data to be hashed
096: * @see #doFinal(byte[], int, int, byte[], int)
097: */
098: public void update(byte[] inBuf, int inOff, int inLen) {
099: if (inLen == 0) {
100: return;
101: }
102:
103: // check parameters to prevent VM from crashing
104: int test = inBuf[inOff] + inBuf[inLen - 1]
105: + inBuf[inOff + inLen - 1];
106:
107: nativeUpdate(inBuf, inOff, inLen, state, num, count, data);
108: }
109:
110: /**
111: * Accumulates a hash of the input data. Continues an MD5
112: * message-digest operation, processing another message
113: * block, and updating the internal context.
114: * @param inBuf input buffer of data to be hashed
115: * @param inOff offset within inBuf where input data begins
116: * @param inLen length (in bytes) of data to be hashed
117: * @param state internal hash state
118: * @param num internal hash state
119: * @param count internal hash state
120: * @param data internal hash state
121: */
122: private static native void nativeUpdate(byte[] inBuf, int inOff,
123: int inLen, int[] state, int[] num, int[] count, int[] data);
124:
125: /**
126: * Completes the hash computation by performing final operations
127: * such as padding. The digest is reset after this call is made.
128: *
129: * @param buf output buffer for the computed digest
130: *
131: * @param offset offset into the output buffer to begin storing the digest
132: *
133: * @param len number of bytes within buf allotted for the digest
134: *
135: * @return the number of bytes placed into <code>buf</code>
136: *
137: * @exception DigestException if an error occurs.
138: */
139: public int digest(byte[] buf, int offset, int len)
140: throws DigestException {
141: if (len < getDigestLength()) {
142: throw new DigestException("Buffer too short.");
143: }
144:
145: // check the parameters to prevent a VM crash
146: int test = buf[offset] + buf[offset + getDigestLength() - 1];
147:
148: nativeFinal(null, 0, 0, buf, offset, state, num, count, data);
149: return getDigestLength();
150: }
151:
152: /**
153: * Generates a hash of all/last input data. Completes and returns the
154: * hash compuatation after performing final operations such as padding.
155: * The MessageDigest object is reset after this call.
156: * @param inBuf input buffer of data to be hashed
157: * @param inOff offset within inBuf where input data begins
158: * @param inLen length (in bytes) of data to be hashed
159: * @param outBuf output buffer where the hash should be placed
160: * @param outOff offset within outBuf where the resulting hash begins
161: * @param state internal hash state
162: * @param num internal hash state
163: * @param count internal hash state
164: * @param data internal hash state
165: */
166: private static native void nativeFinal(byte[] inBuf, int inOff,
167: int inLen, byte[] outBuf, int outOff, int[] state,
168: int[] num, int[] count, int[] data);
169:
170: /**
171: * Clones the MessageDigest object.
172: * @return a clone of this object
173: */
174: public Object clone() {
175: MD5 cpy = new MD5();
176:
177: System.arraycopy(this .state, 0, cpy.state, 0, 4);
178: System.arraycopy(this .num, 0, cpy.num, 0, 1);
179: System.arraycopy(this .data, 0, cpy.data, 0, 16);
180: System.arraycopy(this .count, 0, cpy.count, 0, 2);
181: return cpy;
182: }
183: }
|