1. /*
  2. * @(#)DigestInputStream.java 1.31 01/11/29
  3. *
  4. * Copyright 2002 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.31 01/11/29
  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. */
  68. public MessageDigest getMessageDigest() {
  69. return digest;
  70. }
  71. /**
  72. * Associates the specified message digest with this stream.
  73. *
  74. * @param digest the message digest to be associated with this stream.
  75. */
  76. public void setMessageDigest(MessageDigest digest) {
  77. this.digest = digest;
  78. }
  79. /**
  80. * Reads a byte, and updates the message digest (if the digest
  81. * function is on). That is, this method reads a byte from the
  82. * input stream, blocking until the byte is actually read. If the
  83. * digest function is on (see {@link on(boolean) on}), this method
  84. * will then call <code>update</code> on the message digest associated
  85. * with this stream, passing it the byte read.
  86. *
  87. * @return the byte read.
  88. *
  89. * @exception IOException if an I/O error occurs.
  90. *
  91. * @see MessageDigest#update(byte)
  92. */
  93. public int read() throws IOException {
  94. int ch = in.read();
  95. if (on && ch != -1) {
  96. digest.update((byte)ch);
  97. }
  98. return ch;
  99. }
  100. /**
  101. * Reads into a byte array, and updates the message digest (if the
  102. * digest function is on). That is, this method reads up to
  103. * <code>len</code> bytes from the input stream into the array
  104. * <code>b</code>, starting at offset <code>off</code>. This method
  105. * blocks until the data is actually
  106. * read. If the digest function is on (see
  107. * {@link on(boolean) on}), this method will then call <code>update</code>
  108. * on the message digest associated with this stream, passing it
  109. * the data.
  110. *
  111. * @param b the array into which the data is read.
  112. *
  113. * @param off the starting offset into <code>b</code> of where the
  114. * data should be placed.
  115. *
  116. * @param len the maximum number of bytes to be read from the input
  117. * stream into b, starting at offset <code>off</code>.
  118. *
  119. * @return the actual number of bytes read. This is less than
  120. * <code>len</code> if the end of the stream is reached prior to
  121. * reading <code>len</code> bytes. -1 is returned if no bytes were
  122. * read because the end of the stream had already been reached when
  123. * the call was made.
  124. *
  125. * @exception IOException if an I/O error occurs.
  126. *
  127. * @see MessageDigest#update(byte[], int, int)
  128. */
  129. public int read(byte[] b, int off, int len) throws IOException {
  130. int result = in.read(b, off, len);
  131. if (on && result != -1) {
  132. digest.update(b, off, result);
  133. }
  134. return result;
  135. }
  136. /**
  137. * Turns the digest function on or off. The default is on. When
  138. * it is on, a call to one of the <code>read</code> methods results in an
  139. * update on the message digest. But when it is off, the message
  140. * digest is not updated.
  141. *
  142. * @param on true to turn the digest function on, false to turn
  143. * it off.
  144. */
  145. public void on(boolean on) {
  146. this.on = on;
  147. }
  148. /**
  149. * Prints a string representation of this digest input stream and
  150. * its associated message digest object.
  151. */
  152. public String toString() {
  153. return "[Digest Input Stream] " + digest.toString();
  154. }
  155. }