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 SHA-1 message digest algorithm.
031: */
032: final class SHA extends MessageDigest {
033: /*
034: * The compute intensive operations are implemented in C
035: * based on the OpenSSL SHA code (from pilotSSLeay). Here we
036: * replicate the state the C code needs.
037: */
038:
039: /** State needed for SHA hash. */
040: private int[] state = new int[5]; // h0 ... h4
041: /** State needed for SHA hash. */
042: private int[] num = new int[1];
043: /** State needed for SHA hash. */
044: private int[] count = new int[2]; // Nl and Nh
045: /** State needed for SHA hash. */
046: private int[] data = new int[16]; // data block
047:
048: /** Create SHA digest object. */
049: SHA() {
050: reset();
051: }
052:
053: /**
054: * Gets the message digest algorithm.
055: * @return algorithm implemented by this MessageDigest object
056: */
057: public String getAlgorithm() {
058: return "SHA-1";
059: }
060:
061: /**
062: * Gets the length (in bytes) of the hash.
063: * @return byte-length of the hash produced by this object
064: */
065: public int getDigestLength() {
066: return 20;
067: }
068:
069: /**
070: * Resets the MessageDigest to the initial state for further use.
071: */
072: public void reset() {
073: // SHA1 initialization constants
074: state[0] = 0x67452301;
075: state[1] = 0xEFCDAB89;
076: state[2] = 0x98BADCFE;
077: state[3] = 0x10325476;
078: state[4] = 0xC3D2E1F0;
079: num[0] = 0;
080: count[0] = count[1] = 0;
081: for (int i = 0; i < data.length; i++)
082: data[i] = 0;
083: }
084:
085: /**
086: * Accumulates a hash of the input data. This method is useful when
087: * the input data to be hashed is not available in one byte array.
088: * @param inBuf input buffer of data to be hashed
089: * @param inOff offset within inBuf where input data begins
090: * @param inLen length (in bytes) of data to be hashed
091: * @see #doFinal(byte[], int, int, byte[], int)
092: */
093: public void update(byte[] inBuf, int inOff, int inLen) {
094: if (inLen == 0) {
095: return;
096: }
097:
098: // check parameters to avoid a VM crash
099: int test = inBuf[inOff] + inBuf[inLen - 1]
100: + inBuf[inOff + inLen - 1];
101: nativeUpdate(inBuf, inOff, inLen, state, num, count, data);
102: }
103:
104: /**
105: * Accumulates a hash of the input data. This method is useful when
106: * the input data to be hashed is not available in one byte array.
107: * @param inBuf input buffer of data to be hashed
108: * @param inOff offset within inBuf where input data begins
109: * @param inLen length (in bytes) of data to be hashed
110: * @param state internal hash state
111: * @param num internal hash state
112: * @param count internal hash state
113: * @param data internal hash state
114: */
115: private static native void nativeUpdate(byte[] inBuf, int inOff,
116: int inLen, int[] state, int[] num, int[] count, int[] data);
117:
118: /**
119: * Completes the hash computation by performing final operations
120: * such as padding. The digest is reset after this call is made.
121: *
122: * @param buf output buffer for the computed digest
123: *
124: * @param offset offset into the output buffer to begin storing the digest
125: *
126: * @param len number of bytes within buf allotted for the digest
127: *
128: * @return the number of bytes placed into <code>buf</code>
129: *
130: * @exception DigestException if an error occurs.
131: */
132: public int digest(byte[] buf, int offset, int len)
133: throws DigestException {
134: if (len < getDigestLength()) {
135: throw new DigestException("Buffer too short.");
136: }
137:
138: // check the parameters to prevent a VM crash
139: int test = buf[offset] + buf[offset + getDigestLength() - 1];
140:
141: nativeFinal(null, 0, 0, buf, offset, state, num, count, data);
142: return getDigestLength();
143: }
144:
145: /**
146: * Generates a hash of all/last input data. Completes and returns the
147: * hash compuatation after performing final operations such as padding.
148: * The MessageDigest object is reset after this call.
149: * @param inBuf input buffer of data to be hashed
150: * @param inOff offset within inBuf where input data begins
151: * @param inLen length (in bytes) of data to be hashed
152: * @param outBuf output buffer where the hash should be placed
153: * @param outOff offset within outBuf where the resulting hash begins
154: * @param state internal hash state
155: * @param num internal hash state
156: * @param count internal hash state
157: * @param data internal hash state
158: */
159: private static native void nativeFinal(byte[] inBuf, int inOff,
160: int inLen, byte[] outBuf, int outOff, int[] state,
161: int[] num, int[] count, int[] data);
162:
163: /**
164: * Clones the MessageDigest object.
165: * @return a clone of this object
166: */
167: public Object clone() {
168: SHA cpy = new SHA();
169:
170: System
171: .arraycopy(this .state, 0, cpy.state, 0,
172: this .state.length);
173: System.arraycopy(this .num, 0, cpy.num, 0, this .num.length);
174: System
175: .arraycopy(this .count, 0, cpy.count, 0,
176: this .count.length);
177: System.arraycopy(this .data, 0, cpy.data, 0, this.data.length);
178: return cpy;
179: }
180: }
|