Home » openjdk-7 » javax » crypto » [javadoc | source]

    1   /*
    2    * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package javax.crypto;
   27   
   28   import java.io;
   29   
   30   /**
   31    * A CipherInputStream is composed of an InputStream and a Cipher so
   32    * that read() methods return data that are read in from the
   33    * underlying InputStream but have been additionally processed by the
   34    * Cipher.  The Cipher must be fully initialized before being used by
   35    * a CipherInputStream.
   36    *
   37    * <p> For example, if the Cipher is initialized for decryption, the
   38    * CipherInputStream will attempt to read in data and decrypt them,
   39    * before returning the decrypted data.
   40    *
   41    * <p> This class adheres strictly to the semantics, especially the
   42    * failure semantics, of its ancestor classes
   43    * java.io.FilterInputStream and java.io.InputStream.  This class has
   44    * exactly those methods specified in its ancestor classes, and
   45    * overrides them all.  Moreover, this class catches all exceptions
   46    * that are not thrown by its ancestor classes.  In particular, the
   47    * <code>skip</code> method skips, and the <code>available</code>
   48    * method counts only data that have been processed by the encapsulated Cipher.
   49    *
   50    * <p> It is crucial for a programmer using this class not to use
   51    * methods that are not defined or overriden in this class (such as a
   52    * new method or constructor that is later added to one of the super
   53    * classes), because the design and implementation of those methods
   54    * are unlikely to have considered security impact with regard to
   55    * CipherInputStream.
   56    *
   57    * @author  Li Gong
   58    * @see     java.io.InputStream
   59    * @see     java.io.FilterInputStream
   60    * @see     javax.crypto.Cipher
   61    * @see     javax.crypto.CipherOutputStream
   62    *
   63    * @since 1.4
   64    */
   65   
   66   public class CipherInputStream extends FilterInputStream {
   67   
   68       // the cipher engine to use to process stream data
   69       private Cipher cipher;
   70   
   71       // the underlying input stream
   72       private InputStream input;
   73   
   74       /* the buffer holding data that have been read in from the
   75          underlying stream, but have not been processed by the cipher
   76          engine. the size 512 bytes is somewhat randomly chosen */
   77       private byte[] ibuffer = new byte[512];
   78   
   79       // having reached the end of the underlying input stream
   80       private boolean done = false;
   81   
   82       /* the buffer holding data that have been processed by the cipher
   83          engine, but have not been read out */
   84       private byte[] obuffer;
   85       // the offset pointing to the next "new" byte
   86       private int ostart = 0;
   87       // the offset pointing to the last "new" byte
   88       private int ofinish = 0;
   89   
   90       /**
   91        * private convenience function.
   92        *
   93        * Entry condition: ostart = ofinish
   94        *
   95        * Exit condition: ostart <= ofinish
   96        *
   97        * return (ofinish-ostart) (we have this many bytes for you)
   98        * return 0 (no data now, but could have more later)
   99        * return -1 (absolutely no more data)
  100        */
  101       private int getMoreData() throws IOException {
  102           if (done) return -1;
  103           int readin = input.read(ibuffer);
  104           if (readin == -1) {
  105               done = true;
  106               try {
  107                   obuffer = cipher.doFinal();
  108               }
  109               catch (IllegalBlockSizeException e) {obuffer = null;}
  110               catch (BadPaddingException e) {obuffer = null;}
  111               if (obuffer == null)
  112                   return -1;
  113               else {
  114                   ostart = 0;
  115                   ofinish = obuffer.length;
  116                   return ofinish;
  117               }
  118           }
  119           try {
  120               obuffer = cipher.update(ibuffer, 0, readin);
  121           } catch (IllegalStateException e) {obuffer = null;};
  122           ostart = 0;
  123           if (obuffer == null)
  124               ofinish = 0;
  125           else ofinish = obuffer.length;
  126           return ofinish;
  127       }
  128   
  129       /**
  130        * Constructs a CipherInputStream from an InputStream and a
  131        * Cipher.
  132        * <br>Note: if the specified input stream or cipher is
  133        * null, a NullPointerException may be thrown later when
  134        * they are used.
  135        * @param is the to-be-processed input stream
  136        * @param c an initialized Cipher object
  137        */
  138       public CipherInputStream(InputStream is, Cipher c) {
  139           super(is);
  140           input = is;
  141           cipher = c;
  142       }
  143   
  144       /**
  145        * Constructs a CipherInputStream from an InputStream without
  146        * specifying a Cipher. This has the effect of constructing a
  147        * CipherInputStream using a NullCipher.
  148        * <br>Note: if the specified input stream is null, a
  149        * NullPointerException may be thrown later when it is used.
  150        * @param is the to-be-processed input stream
  151        */
  152       protected CipherInputStream(InputStream is) {
  153           super(is);
  154           input = is;
  155           cipher = new NullCipher();
  156       }
  157   
  158       /**
  159        * Reads the next byte of data from this input stream. The value
  160        * byte is returned as an <code>int</code> in the range
  161        * <code>0</code> to <code>255</code>. If no byte is available
  162        * because the end of the stream has been reached, the value
  163        * <code>-1</code> is returned. This method blocks until input data
  164        * is available, the end of the stream is detected, or an exception
  165        * is thrown.
  166        * <p>
  167        *
  168        * @return  the next byte of data, or <code>-1</code> if the end of the
  169        *          stream is reached.
  170        * @exception  IOException  if an I/O error occurs.
  171        * @since JCE1.2
  172        */
  173       public int read() throws IOException {
  174           if (ostart >= ofinish) {
  175               // we loop for new data as the spec says we are blocking
  176               int i = 0;
  177               while (i == 0) i = getMoreData();
  178               if (i == -1) return -1;
  179           }
  180           return ((int) obuffer[ostart++] & 0xff);
  181       };
  182   
  183       /**
  184        * Reads up to <code>b.length</code> bytes of data from this input
  185        * stream into an array of bytes.
  186        * <p>
  187        * The <code>read</code> method of <code>InputStream</code> calls
  188        * the <code>read</code> method of three arguments with the arguments
  189        * <code>b</code>, <code>0</code>, and <code>b.length</code>.
  190        *
  191        * @param      b   the buffer into which the data is read.
  192        * @return     the total number of bytes read into the buffer, or
  193        *             <code>-1</code> is there is no more data because the end of
  194        *             the stream has been reached.
  195        * @exception  IOException  if an I/O error occurs.
  196        * @see        java.io.InputStream#read(byte[], int, int)
  197        * @since      JCE1.2
  198        */
  199       public int read(byte b[]) throws IOException {
  200           return read(b, 0, b.length);
  201       }
  202   
  203       /**
  204        * Reads up to <code>len</code> bytes of data from this input stream
  205        * into an array of bytes. This method blocks until some input is
  206        * available. If the first argument is <code>null,</code> up to
  207        * <code>len</code> bytes are read and discarded.
  208        *
  209        * @param      b     the buffer into which the data is read.
  210        * @param      off   the start offset in the destination array
  211        *                   <code>buf</code>
  212        * @param      len   the maximum number of bytes read.
  213        * @return     the total number of bytes read into the buffer, or
  214        *             <code>-1</code> if there is no more data because the end of
  215        *             the stream has been reached.
  216        * @exception  IOException  if an I/O error occurs.
  217        * @see        java.io.InputStream#read()
  218        * @since      JCE1.2
  219        */
  220       public int read(byte b[], int off, int len) throws IOException {
  221           if (ostart >= ofinish) {
  222               // we loop for new data as the spec says we are blocking
  223               int i = 0;
  224               while (i == 0) i = getMoreData();
  225               if (i == -1) return -1;
  226           }
  227           if (len <= 0) {
  228               return 0;
  229           }
  230           int available = ofinish - ostart;
  231           if (len < available) available = len;
  232           if (b != null) {
  233               System.arraycopy(obuffer, ostart, b, off, available);
  234           }
  235           ostart = ostart + available;
  236           return available;
  237       }
  238   
  239       /**
  240        * Skips <code>n</code> bytes of input from the bytes that can be read
  241        * from this input stream without blocking.
  242        *
  243        * <p>Fewer bytes than requested might be skipped.
  244        * The actual number of bytes skipped is equal to <code>n</code> or
  245        * the result of a call to
  246        * {@link #available() <code>available</code>},
  247        * whichever is smaller.
  248        * If <code>n</code> is less than zero, no bytes are skipped.
  249        *
  250        * <p>The actual number of bytes skipped is returned.
  251        *
  252        * @param      n the number of bytes to be skipped.
  253        * @return     the actual number of bytes skipped.
  254        * @exception  IOException  if an I/O error occurs.
  255        * @since JCE1.2
  256        */
  257       public long skip(long n) throws IOException {
  258           int available = ofinish - ostart;
  259           if (n > available) {
  260               n = available;
  261           }
  262           if (n < 0) {
  263               return 0;
  264           }
  265           ostart += n;
  266           return n;
  267       }
  268   
  269       /**
  270        * Returns the number of bytes that can be read from this input
  271        * stream without blocking. The <code>available</code> method of
  272        * <code>InputStream</code> returns <code>0</code>. This method
  273        * <B>should</B> be overridden by subclasses.
  274        *
  275        * @return     the number of bytes that can be read from this input stream
  276        *             without blocking.
  277        * @exception  IOException  if an I/O error occurs.
  278        * @since      JCE1.2
  279        */
  280       public int available() throws IOException {
  281           return (ofinish - ostart);
  282       }
  283   
  284       /**
  285        * Closes this input stream and releases any system resources
  286        * associated with the stream.
  287        * <p>
  288        * The <code>close</code> method of <code>CipherInputStream</code>
  289        * calls the <code>close</code> method of its underlying input
  290        * stream.
  291        *
  292        * @exception  IOException  if an I/O error occurs.
  293        * @since JCE1.2
  294        */
  295       public void close() throws IOException {
  296           input.close();
  297           try {
  298               // throw away the unprocessed data
  299               cipher.doFinal();
  300           }
  301           catch (BadPaddingException ex) {
  302           }
  303           catch (IllegalBlockSizeException ex) {
  304           }
  305           ostart = 0;
  306           ofinish = 0;
  307       }
  308   
  309       /**
  310        * Tests if this input stream supports the <code>mark</code>
  311        * and <code>reset</code> methods, which it does not.
  312        *
  313        * @return  <code>false</code>, since this class does not support the
  314        *          <code>mark</code> and <code>reset</code> methods.
  315        * @see     java.io.InputStream#mark(int)
  316        * @see     java.io.InputStream#reset()
  317        * @since   JCE1.2
  318        */
  319       public boolean markSupported() {
  320           return false;
  321       }
  322   }

Home » openjdk-7 » javax » crypto » [javadoc | source]