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