001         package com.croftsoft.core.util.cache.secure;
002    
003         import java.io.*;
004         import java.security.*;
005    
006         /*********************************************************************
007         * A FilterInputStream which will throw a SecurityException if the
008         * stream content does not have the digest expected.
009         *
010         * @see
011         *   java.security.DigestInputStream
012         * @see
013         *   java.security.MessageDigest
014         *
015         * @version
016         *   1999-04-13
017         * @author
018         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
019         *********************************************************************/
020    
021         public class  SecureInputStream extends FilterInputStream
022         //////////////////////////////////////////////////////////////////////
023         //////////////////////////////////////////////////////////////////////
024         {
025    
026         /** The expected digest. */
027         private byte [ ]  digest;
028    
029         //////////////////////////////////////////////////////////////////////
030         // Constructor method
031         //////////////////////////////////////////////////////////////////////
032    
033         /*********************************************************************
034         * @param  algorithm
035         *   The MessageDigest algorithm to use.
036         * @param  digest
037         *   The expected digest.
038         *********************************************************************/
039         public  SecureInputStream (
040           InputStream  inputStream,
041           String       algorithm,
042           byte [ ]     digest )
043           throws NoSuchAlgorithmException
044         //////////////////////////////////////////////////////////////////////
045         {
046           super ( new DigestInputStream ( inputStream,
047             MessageDigest.getInstance ( algorithm ) ) );
048    
049           this.digest = digest;
050         }
051    
052         //////////////////////////////////////////////////////////////////////
053         //////////////////////////////////////////////////////////////////////
054    
055         /*********************************************************************
056         * @throws  SecurityException
057         *   If the end of the stream is reached and the digest is not what
058         *   is expected.
059         *********************************************************************/
060         public int  read ( ) throws IOException
061         //////////////////////////////////////////////////////////////////////
062         {
063           int  i = super.read ( );
064    
065           if ( i < 0 ) checkDigest ( );
066    
067           return i;
068         }
069    
070         /*********************************************************************
071         * @throws  SecurityException
072         *   If the end of the stream is reached and the digest is not what
073         *   is expected.
074         *********************************************************************/
075         public int  read ( byte [ ]  byteArray, int  offset, int  length )
076           throws IOException
077         //////////////////////////////////////////////////////////////////////
078         {
079           int  i = super.read ( byteArray, offset, length );
080    
081           if ( i < length ) checkDigest ( );
082    
083           return i;
084         }
085    
086         private void  checkDigest ( ) throws IOException
087         //////////////////////////////////////////////////////////////////////
088         {
089           if ( !MessageDigest.isEqual ( digest,
090               ( ( DigestInputStream ) in ).getMessageDigest ( ).digest ( ) ) )
091           {
092             throw new IOException ( "bad message digest" );
093           }
094         }
095    
096         //////////////////////////////////////////////////////////////////////
097         //////////////////////////////////////////////////////////////////////
098         }