1. /*
  2. * @(#)MessageDigestSpi.java 1.15 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.security;
  8. import java.util.*;
  9. import java.lang.*;
  10. import java.io.IOException;
  11. import java.io.ByteArrayOutputStream;
  12. import java.io.PrintStream;
  13. import java.io.InputStream;
  14. import java.io.ByteArrayInputStream;
  15. import java.nio.ByteBuffer;
  16. import sun.security.jca.JCAUtil;
  17. /**
  18. * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>)
  19. * for the <code>MessageDigest</code> class, which provides the functionality
  20. * of a message digest algorithm, such as MD5 or SHA. Message digests are
  21. * secure one-way hash functions that take arbitrary-sized data and output a
  22. * fixed-length hash value.
  23. *
  24. * <p> All the abstract methods in this class must be implemented by a
  25. * cryptographic service provider who wishes to supply the implementation
  26. * of a particular message digest algorithm.
  27. *
  28. * <p> Implementations are free to implement the Cloneable interface.
  29. *
  30. * @author Benjamin Renaud
  31. *
  32. * @version 1.15, 12/19/03
  33. *
  34. * @see MessageDigest
  35. */
  36. public abstract class MessageDigestSpi {
  37. /**
  38. * Returns the digest length in bytes.
  39. *
  40. * <p>This concrete method has been added to this previously-defined
  41. * abstract class. (For backwards compatibility, it cannot be abstract.)
  42. *
  43. * <p>The default behavior is to return 0.
  44. *
  45. * <p>This method may be overridden by a provider to return the digest
  46. * length.
  47. *
  48. * @return the digest length in bytes.
  49. *
  50. * @since 1.2
  51. */
  52. protected int engineGetDigestLength() {
  53. return 0;
  54. }
  55. /**
  56. * Updates the digest using the specified byte.
  57. *
  58. * @param input the byte to use for the update.
  59. */
  60. protected abstract void engineUpdate(byte input);
  61. /**
  62. * Updates the digest using the specified array of bytes,
  63. * starting at the specified offset.
  64. *
  65. * @param input the array of bytes to use for the update.
  66. *
  67. * @param offset the offset to start from in the array of bytes.
  68. *
  69. * @param len the number of bytes to use, starting at
  70. * <code>offset</code>.
  71. */
  72. protected abstract void engineUpdate(byte[] input, int offset, int len);
  73. /**
  74. * Update the digest using the specified ByteBuffer. The digest is
  75. * updated using the <code>input.remaining()</code> bytes starting
  76. * at <code>input.position()</code>.
  77. * Upon return, the buffer's position will be equal to its limit;
  78. * its limit will not have changed.
  79. *
  80. * @param input the ByteBuffer
  81. * @since 1.5
  82. */
  83. protected void engineUpdate(ByteBuffer input) {
  84. if (input.hasRemaining() == false) {
  85. return;
  86. }
  87. if (input.hasArray()) {
  88. byte[] b = input.array();
  89. int ofs = input.arrayOffset();
  90. int pos = input.position();
  91. int lim = input.limit();
  92. engineUpdate(b, ofs + pos, lim - pos);
  93. input.position(lim);
  94. } else {
  95. int len = input.remaining();
  96. byte[] b = new byte[JCAUtil.getTempArraySize(len)];
  97. while (len > 0) {
  98. int chunk = Math.min(len, b.length);
  99. input.get(b, 0, chunk);
  100. engineUpdate(b, 0, chunk);
  101. len -= chunk;
  102. }
  103. }
  104. }
  105. /**
  106. * Completes the hash computation by performing final
  107. * operations such as padding. Once <code>engineDigest</code> has
  108. * been called, the engine should be reset (see
  109. * {@link #engineReset() engineReset}).
  110. * Resetting is the responsibility of the
  111. * engine implementor.
  112. *
  113. * @return the array of bytes for the resulting hash value.
  114. */
  115. protected abstract byte[] engineDigest();
  116. /**
  117. * Completes the hash computation by performing final
  118. * operations such as padding. Once <code>engineDigest</code> has
  119. * been called, the engine should be reset (see
  120. * {@link #engineReset() engineReset}).
  121. * Resetting is the responsibility of the
  122. * engine implementor.
  123. *
  124. * This method should be abstract, but we leave it concrete for
  125. * binary compatibility. Knowledgeable providers should override this
  126. * method.
  127. *
  128. * @param buf the output buffer in which to store the digest
  129. *
  130. * @param offset offset to start from in the output buffer
  131. *
  132. * @param len number of bytes within buf allotted for the digest.
  133. * Both this default implementation and the SUN provider do not
  134. * return partial digests. The presence of this parameter is solely
  135. * for consistency in our API's. If the value of this parameter is less
  136. * than the actual digest length, the method will throw a DigestException.
  137. * This parameter is ignored if its value is greater than or equal to
  138. * the actual digest length.
  139. *
  140. * @return the length of the digest stored in the output buffer.
  141. *
  142. * @exception DigestException if an error occurs.
  143. *
  144. * @since 1.2
  145. */
  146. protected int engineDigest(byte[] buf, int offset, int len)
  147. throws DigestException {
  148. byte[] digest = engineDigest();
  149. if (len < digest.length)
  150. throw new DigestException("partial digests not returned");
  151. if (buf.length - offset < digest.length)
  152. throw new DigestException("insufficient space in the output "
  153. + "buffer to store the digest");
  154. System.arraycopy(digest, 0, buf, offset, digest.length);
  155. return digest.length;
  156. }
  157. /**
  158. * Resets the digest for further use.
  159. */
  160. protected abstract void engineReset();
  161. /**
  162. * Returns a clone if the implementation is cloneable.
  163. *
  164. * @return a clone if the implementation is cloneable.
  165. *
  166. * @exception CloneNotSupportedException if this is called on an
  167. * implementation that does not support <code>Cloneable</code>.
  168. */
  169. public Object clone() throws CloneNotSupportedException {
  170. if (this instanceof Cloneable) {
  171. return super.clone();
  172. } else {
  173. throw new CloneNotSupportedException();
  174. }
  175. }
  176. }