1. /*
  2. * @(#)DigestInputStream.java 1.37 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.io.IOException;
  9. import java.io.EOFException;
  10. import java.io.InputStream;
  11. import java.io.FilterInputStream;
  12. import java.io.PrintStream;
  13. import java.io.ByteArrayInputStream;
  14. /**
  15. * A transparent stream that updates the associated message digest using
  16. * the bits going through the stream.
  17. *
  18. * <p>To complete the message digest computation, call one of the
  19. * <code>digest</code> methods on the associated message
  20. * digest after your calls to one of this digest input stream's
  21. * {@link #read() read} methods.
  22. *
  23. * <p>It is possible to turn this stream on or off (see
  24. * {@link #on(boolean) on}). When it is on, a call to one of the
  25. * <code>read</code> methods
  26. * results in an update on the message digest. But when it is off,
  27. * the message digest is not updated. The default is for the stream
  28. * to be on.
  29. *
  30. * <p>Note that digest objects can compute only one digest (see
  31. * {@link MessageDigest}),
  32. * so that in order to compute intermediate digests, a caller should
  33. * retain a handle onto the digest object, and clone it for each
  34. * digest to be computed, leaving the orginal digest untouched.
  35. *
  36. * @see MessageDigest
  37. *
  38. * @see DigestOutputStream
  39. *
  40. * @version 1.37 03/12/19
  41. * @author Benjamin Renaud
  42. */
  43. public class DigestInputStream extends FilterInputStream {
  44. /* NOTE: This should be made a generic UpdaterInputStream */
  45. /* Are we on or off? */
  46. private boolean on = true;
  47. /**
  48. * The message digest associated with this stream.
  49. */
  50. protected MessageDigest digest;
  51. /**
  52. * Creates a digest input stream, using the specified input stream
  53. * and message digest.
  54. *
  55. * @param stream the input stream.
  56. *
  57. * @param digest the message digest to associate with this stream.
  58. */
  59. public DigestInputStream(InputStream stream, MessageDigest digest) {
  60. super(stream);
  61. setMessageDigest(digest);
  62. }
  63. /**
  64. * Returns the message digest associated with this stream.
  65. *
  66. * @return the message digest associated with this stream.
  67. * @see #setMessageDigest(java.security.MessageDigest)
  68. */
  69. public MessageDigest getMessageDigest() {
  70. return digest;
  71. }
  72. /**
  73. * Associates the specified message digest with this stream.
  74. *
  75. * @param digest the message digest to be associated with this stream.
  76. * @see #getMessageDigest()
  77. */
  78. public void setMessageDigest(MessageDigest digest) {
  79. this.digest = digest;
  80. }
  81. /**
  82. * Reads a byte, and updates the message digest (if the digest
  83. * function is on). That is, this method reads a byte from the
  84. * input stream, blocking until the byte is actually read. If the
  85. * digest function is on (see {@link #on(boolean) on}), this method
  86. * will then call <code>update</code> on the message digest associated
  87. * with this stream, passing it the byte read.
  88. *
  89. * @return the byte read.
  90. *
  91. * @exception IOException if an I/O error occurs.
  92. *
  93. * @see MessageDigest#update(byte)
  94. */
  95. public int read() throws IOException {
  96. int ch = in.read();
  97. if (on && ch != -1) {
  98. digest.update((byte)ch);
  99. }
  100. return ch;
  101. }
  102. /**
  103. * Reads into a byte array, and updates the message digest (if the
  104. * digest function is on). That is, this method reads up to
  105. * <code>len</code> bytes from the input stream into the array
  106. * <code>b</code>, starting at offset <code>off</code>. This method
  107. * blocks until the data is actually
  108. * read. If the digest function is on (see
  109. * {@link #on(boolean) on}), this method will then call <code>update</code>
  110. * on the message digest associated with this stream, passing it
  111. * the data.
  112. *
  113. * @param b the array into which the data is read.
  114. *
  115. * @param off the starting offset into <code>b</code> of where the
  116. * data should be placed.
  117. *
  118. * @param len the maximum number of bytes to be read from the input
  119. * stream into b, starting at offset <code>off</code>.
  120. *
  121. * @return the actual number of bytes read. This is less than
  122. * <code>len</code> if the end of the stream is reached prior to
  123. * reading <code>len</code> bytes. -1 is returned if no bytes were
  124. * read because the end of the stream had already been reached when
  125. * the call was made.
  126. *
  127. * @exception IOException if an I/O error occurs.
  128. *
  129. * @see MessageDigest#update(byte[], int, int)
  130. */
  131. public int read(byte[] b, int off, int len) throws IOException {
  132. int result = in.read(b, off, len);
  133. if (on && result != -1) {
  134. digest.update(b, off, result);
  135. }
  136. return result;
  137. }
  138. /**
  139. * Turns the digest function on or off. The default is on. When
  140. * it is on, a call to one of the <code>read</code> methods results in an
  141. * update on the message digest. But when it is off, the message
  142. * digest is not updated.
  143. *
  144. * @param on true to turn the digest function on, false to turn
  145. * it off.
  146. */
  147. public void on(boolean on) {
  148. this.on = on;
  149. }
  150. /**
  151. * Prints a string representation of this digest input stream and
  152. * its associated message digest object.
  153. */
  154. public String toString() {
  155. return "[Digest Input Stream] " + digest.toString();
  156. }
  157. }