001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.security;
019:
020: import java.nio.ByteBuffer;
021:
022: import org.apache.harmony.security.fortress.Engine;
023: import org.apache.harmony.security.internal.nls.Messages;
024:
025: public abstract class MessageDigest extends MessageDigestSpi {
026:
027: // The service name
028: private static final String SERVICE = "MessageDigest"; //$NON-NLS-1$
029:
030: // Used to access common engine functionality
031: private static Engine engine = new Engine(SERVICE);
032:
033: // The provider
034: private Provider provider;
035:
036: // The algorithm.
037: private String algorithm;
038:
039: /**
040: * @com.intel.drl.spec_ref
041: *
042: */
043: protected MessageDigest(String algorithm) {
044: this .algorithm = algorithm;
045: }
046:
047: /**
048: * @com.intel.drl.spec_ref
049: *
050: */
051: public static MessageDigest getInstance(String algorithm)
052: throws NoSuchAlgorithmException {
053: if (algorithm == null) {
054: throw new NullPointerException(Messages
055: .getString("security.01")); //$NON-NLS-1$
056: }
057: MessageDigest result;
058: synchronized (engine) {
059: engine.getInstance(algorithm, null);
060: if (engine.spi instanceof MessageDigest) {
061: result = (MessageDigest) engine.spi;
062: result.algorithm = algorithm;
063: result.provider = engine.provider;
064: return result;
065: } else {
066: result = new MessageDigestImpl(
067: (MessageDigestSpi) engine.spi, engine.provider,
068: algorithm);
069: return result;
070: }
071: }
072: }
073:
074: /**
075: * @com.intel.drl.spec_ref
076: *
077: */
078: public static MessageDigest getInstance(String algorithm,
079: String provider) throws NoSuchAlgorithmException,
080: NoSuchProviderException {
081: if ((provider == null) || (provider.length() == 0)) {
082: throw new IllegalArgumentException(Messages
083: .getString("security.02")); //$NON-NLS-1$
084: }
085: Provider p = Security.getProvider(provider);
086: if (p == null) {
087: throw new NoSuchProviderException(Messages.getString(
088: "security.03", provider)); //$NON-NLS-1$
089: }
090: return getInstance(algorithm, p);
091: }
092:
093: /**
094: * Answers a new MessageDigest which is capable of running the algorithm
095: * described by the argument. The result will be an instance of a subclass
096: * of MessageDigest which implements that algorithm.
097: *
098: *
099: * @param algorithm
100: * java.lang.String Name of the algorithm desired
101: * @param provider
102: * Provider Provider which has to implement the algorithm
103: * @return MessageDigest a concrete implementation for the algorithm
104: * desired.
105: *
106: * @exception NoSuchAlgorithmException
107: * If the algorithm cannot be found
108: */
109: public static MessageDigest getInstance(String algorithm,
110: Provider provider) throws NoSuchAlgorithmException {
111: if (provider == null) {
112: throw new IllegalArgumentException(Messages
113: .getString("security.04")); //$NON-NLS-1$
114: }
115: if (algorithm == null) {
116: throw new NullPointerException(Messages
117: .getString("security.01")); //$NON-NLS-1$
118: }
119: MessageDigest result;
120: synchronized (engine) {
121: engine.getInstance(algorithm, provider, null);
122: if (engine.spi instanceof MessageDigest) {
123: result = (MessageDigest) engine.spi;
124: result.algorithm = algorithm;
125: result.provider = provider;
126: return result;
127: } else {
128: result = new MessageDigestImpl(
129: (MessageDigestSpi) engine.spi, provider,
130: algorithm);
131: return result;
132: }
133: }
134: }
135:
136: /**
137: * Puts the receiver back in an initial state, such that it is ready to
138: * compute a new hash.
139: */
140: public void reset() {
141: engineReset();
142: }
143:
144: /**
145: * Includes the argument in the hash value computed by the receiver.
146: *
147: * @param arg0
148: * byte the byte to feed to the hash algorithm
149: *
150: * @see #reset()
151: */
152: public void update(byte arg0) {
153: engineUpdate(arg0);
154: }
155:
156: /**
157: * @com.intel.drl.spec_ref
158: *
159: */
160: public void update(byte[] input, int offset, int len) {
161: if (input == null ||
162: // offset < 0 || len < 0 ||
163: // checks for negative values are commented out intentionally
164: // see HARMONY-1120 for details
165: (long) offset + (long) len > input.length) {
166: throw new IllegalArgumentException(Messages
167: .getString("security.05")); //$NON-NLS-1$
168: }
169: engineUpdate(input, offset, len);
170: }
171:
172: /**
173: * @com.intel.drl.spec_ref
174: *
175: */
176: public void update(byte[] input) {
177: if (input == null) {
178: throw new NullPointerException(Messages
179: .getString("security.06")); //$NON-NLS-1$
180: }
181: engineUpdate(input, 0, input.length);
182: }
183:
184: /**
185: * Computes and answers the final hash value that the receiver represents.
186: * After the digest is computed the receiver is reset.
187: *
188: * @return the hash the receiver computed
189: *
190: * @see #reset
191: */
192: public byte[] digest() {
193: return engineDigest();
194: }
195:
196: /**
197: * @com.intel.drl.spec_ref
198: *
199: */
200: public int digest(byte[] buf, int offset, int len)
201: throws DigestException {
202: if (buf == null ||
203: // offset < 0 || len < 0 ||
204: // checks for negative values are commented out intentionally
205: // see HARMONY-1148 for details
206: (long) offset + (long) len > buf.length) {
207: throw new IllegalArgumentException(Messages
208: .getString("security.05")); //$NON-NLS-1$
209: }
210: return engineDigest(buf, offset, len);
211: }
212:
213: /**
214: * @com.intel.drl.spec_ref
215: *
216: */
217: public byte[] digest(byte[] input) {
218: update(input);
219: return digest();
220: }
221:
222: /**
223: * Answers a string containing a concise, human-readable description of the
224: * receiver.
225: *
226: * @return a printable representation for the receiver.
227: */
228: public String toString() {
229: return "MESSAGE DIGEST " + algorithm; //$NON-NLS-1$
230: }
231:
232: /**
233: * Does a simply byte-per-byte compare of the two digests.
234: *
235: * @param digesta
236: * One of the digests to compare
237: * @param digestb
238: * The digest to compare to
239: *
240: * @return <code>true</code> if the two hashes are equal
241: * <code>false</code> if the two hashes are not equal
242: */
243: public static boolean isEqual(byte[] digesta, byte[] digestb) {
244: if (digesta.length != digestb.length) {
245: return false;
246: }
247: for (int i = 0; i < digesta.length; i++) {
248: if (digesta[i] != digestb[i]) {
249: return false;
250: }
251: }
252: return true;
253: }
254:
255: /**
256: * Answers the standard Java Security name for the algorithm being used by
257: * the receiver.
258: *
259: * @return String the name of the algorithm
260: */
261: public final String getAlgorithm() {
262: return algorithm;
263: }
264:
265: /**
266: * Returns the Provider of the digest represented by the receiver.
267: *
268: * @return Provider an instance of a subclass of java.security.Provider
269: */
270: public final Provider getProvider() {
271: return provider;
272: }
273:
274: /**
275: * Return the engine digest length in bytes. Default is 0.
276: *
277: * @return int the engine digest length in bytes
278: *
279: */
280: public final int getDigestLength() {
281: int l = engineGetDigestLength();
282: if (l != 0) {
283: return l;
284: }
285: if (!(this instanceof Cloneable)) {
286: return 0;
287: }
288: try {
289: MessageDigest md = (MessageDigest) clone();
290: return md.digest().length;
291: } catch (CloneNotSupportedException e) {
292: return 0;
293: }
294: }
295:
296: /**
297: * @com.intel.drl.spec_ref
298: *
299: */
300: public Object clone() throws CloneNotSupportedException {
301: if (this instanceof Cloneable) {
302: return super .clone();
303: } else {
304: throw new CloneNotSupportedException();
305: }
306: }
307:
308: /**
309: * @com.intel.drl.spec_ref
310: *
311: */
312: public final void update(ByteBuffer input) {
313: engineUpdate(input);
314: }
315:
316: /**
317: *
318: * The internal MessageDigest implementation
319: *
320: */
321: private static class MessageDigestImpl extends MessageDigest {
322:
323: // MessageDigestSpi implementation
324: private MessageDigestSpi spiImpl;
325:
326: // MessageDigestImpl ctor
327: private MessageDigestImpl(MessageDigestSpi messageDigestSpi,
328: Provider provider, String algorithm) {
329: super (algorithm);
330: super .provider = provider;
331: spiImpl = messageDigestSpi;
332: }
333:
334: // engineReset() implementation
335: protected void engineReset() {
336: spiImpl.engineReset();
337: }
338:
339: // engineDigest() implementation
340: protected byte[] engineDigest() {
341: return spiImpl.engineDigest();
342: }
343:
344: // engineGetDigestLength() implementation
345: protected int engineGetDigestLength() {
346: return spiImpl.engineGetDigestLength();
347: }
348:
349: // engineUpdate() implementation
350: protected void engineUpdate(byte arg0) {
351: spiImpl.engineUpdate(arg0);
352: }
353:
354: // engineUpdate() implementation
355: protected void engineUpdate(byte[] arg0, int arg1, int arg2) {
356: spiImpl.engineUpdate(arg0, arg1, arg2);
357: }
358:
359: // Returns a clone if the spiImpl is cloneable
360: public Object clone() throws CloneNotSupportedException {
361: if (spiImpl instanceof Cloneable) {
362: MessageDigestSpi spi = (MessageDigestSpi) spiImpl
363: .clone();
364: return new MessageDigestImpl(spi, getProvider(),
365: getAlgorithm());
366: } else {
367: throw new CloneNotSupportedException();
368: }
369: }
370: }
371: }
|