001: /*
002: * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package java.security;
027:
028: import java.nio.ByteBuffer;
029:
030: import sun.security.jca.JCAUtil;
031:
032: /**
033: * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
034: * for the <code>MessageDigest</code> class, which provides the functionality
035: * of a message digest algorithm, such as MD5 or SHA. Message digests are
036: * secure one-way hash functions that take arbitrary-sized data and output a
037: * fixed-length hash value.
038: *
039: * <p> All the abstract methods in this class must be implemented by a
040: * cryptographic service provider who wishes to supply the implementation
041: * of a particular message digest algorithm.
042: *
043: * <p> Implementations are free to implement the Cloneable interface.
044: *
045: * @author Benjamin Renaud
046: *
047: * @version 1.23, 05/05/07
048: *
049: * @see MessageDigest
050: */
051:
052: public abstract class MessageDigestSpi {
053:
054: // for re-use in engineUpdate(ByteBuffer input)
055: private byte[] tempArray;
056:
057: /**
058: * Returns the digest length in bytes.
059: *
060: * <p>This concrete method has been added to this previously-defined
061: * abstract class. (For backwards compatibility, it cannot be abstract.)
062: *
063: * <p>The default behavior is to return 0.
064: *
065: * <p>This method may be overridden by a provider to return the digest
066: * length.
067: *
068: * @return the digest length in bytes.
069: *
070: * @since 1.2
071: */
072: protected int engineGetDigestLength() {
073: return 0;
074: }
075:
076: /**
077: * Updates the digest using the specified byte.
078: *
079: * @param input the byte to use for the update.
080: */
081: protected abstract void engineUpdate(byte input);
082:
083: /**
084: * Updates the digest using the specified array of bytes,
085: * starting at the specified offset.
086: *
087: * @param input the array of bytes to use for the update.
088: *
089: * @param offset the offset to start from in the array of bytes.
090: *
091: * @param len the number of bytes to use, starting at
092: * <code>offset</code>.
093: */
094: protected abstract void engineUpdate(byte[] input, int offset,
095: int len);
096:
097: /**
098: * Update the digest using the specified ByteBuffer. The digest is
099: * updated using the <code>input.remaining()</code> bytes starting
100: * at <code>input.position()</code>.
101: * Upon return, the buffer's position will be equal to its limit;
102: * its limit will not have changed.
103: *
104: * @param input the ByteBuffer
105: * @since 1.5
106: */
107: protected void engineUpdate(ByteBuffer input) {
108: if (input.hasRemaining() == false) {
109: return;
110: }
111: if (input.hasArray()) {
112: byte[] b = input.array();
113: int ofs = input.arrayOffset();
114: int pos = input.position();
115: int lim = input.limit();
116: engineUpdate(b, ofs + pos, lim - pos);
117: input.position(lim);
118: } else {
119: int len = input.remaining();
120: int n = JCAUtil.getTempArraySize(len);
121: if ((tempArray == null) || (n > tempArray.length)) {
122: tempArray = new byte[n];
123: }
124: while (len > 0) {
125: int chunk = Math.min(len, tempArray.length);
126: input.get(tempArray, 0, chunk);
127: engineUpdate(tempArray, 0, chunk);
128: len -= chunk;
129: }
130: }
131: }
132:
133: /**
134: * Completes the hash computation by performing final
135: * operations such as padding. Once <code>engineDigest</code> has
136: * been called, the engine should be reset (see
137: * {@link #engineReset() engineReset}).
138: * Resetting is the responsibility of the
139: * engine implementor.
140: *
141: * @return the array of bytes for the resulting hash value.
142: */
143: protected abstract byte[] engineDigest();
144:
145: /**
146: * Completes the hash computation by performing final
147: * operations such as padding. Once <code>engineDigest</code> has
148: * been called, the engine should be reset (see
149: * {@link #engineReset() engineReset}).
150: * Resetting is the responsibility of the
151: * engine implementor.
152: *
153: * This method should be abstract, but we leave it concrete for
154: * binary compatibility. Knowledgeable providers should override this
155: * method.
156: *
157: * @param buf the output buffer in which to store the digest
158: *
159: * @param offset offset to start from in the output buffer
160: *
161: * @param len number of bytes within buf allotted for the digest.
162: * Both this default implementation and the SUN provider do not
163: * return partial digests. The presence of this parameter is solely
164: * for consistency in our API's. If the value of this parameter is less
165: * than the actual digest length, the method will throw a DigestException.
166: * This parameter is ignored if its value is greater than or equal to
167: * the actual digest length.
168: *
169: * @return the length of the digest stored in the output buffer.
170: *
171: * @exception DigestException if an error occurs.
172: *
173: * @since 1.2
174: */
175: protected int engineDigest(byte[] buf, int offset, int len)
176: throws DigestException {
177:
178: byte[] digest = engineDigest();
179: if (len < digest.length)
180: throw new DigestException("partial digests not returned");
181: if (buf.length - offset < digest.length)
182: throw new DigestException(
183: "insufficient space in the output "
184: + "buffer to store the digest");
185: System.arraycopy(digest, 0, buf, offset, digest.length);
186: return digest.length;
187: }
188:
189: /**
190: * Resets the digest for further use.
191: */
192: protected abstract void engineReset();
193:
194: /**
195: * Returns a clone if the implementation is cloneable.
196: *
197: * @return a clone if the implementation is cloneable.
198: *
199: * @exception CloneNotSupportedException if this is called on an
200: * implementation that does not support <code>Cloneable</code>.
201: */
202: public Object clone() throws CloneNotSupportedException {
203: if (this instanceof Cloneable) {
204: return super .clone();
205: } else {
206: throw new CloneNotSupportedException();
207: }
208: }
209: }
|