xjava.security
Class CipherInputStream

java.lang.Object
  |
  +--java.io.InputStream
        |
        +--java.io.FilterInputStream
              |
              +--xjava.security.CipherInputStream

public class CipherInputStream
extends java.io.FilterInputStream

A FilterInputStream that encrypts or decrypts the data passing through it. Typically, this stream would be used as a filter to read an encrypted file. It can also be used to encrypt network communications (although this would normally require use of a stream cipher, or a block cipher in a stream-like mode such as CFB or OFB).

This class has a constructor that takes an input stream and a Cipher as arguments. The cipher is used to encrypt or decrypt all data read through the stream.

The data is encrypted or decrypted, depending on the initialisation state of the Cipher. To get the encryption/decryption result bytes, make one or more calls to the read methods. One read method, with no arguments, returns the next result byte. The other read method returns multiple result bytes at once.

For block ciphers, some buffering of the data received from the input stream is done. The buffer length is calculated as follows:

    buffer length = cipher.getInputBlockSize() +
      (cipher.isPaddingBlockCipher() &&
       cipher.getState() == Cipher.DECRYPT) ? 1 : 0
 
Each read operation will attempt to completely fill the buffer. The maximum number of bytes that can remain unprocessed after each read call is one less than the buffer length. In the case of a padding block cipher in DECRYPT mode, this means that one full ciphertext block may remain unprocessed, because it is necessary to read an extra byte in order to determine whether this is the last block of the stream. (It would be incorrect to process a block without making this check, since it may have padding bytes that need to be stripped out.)

When EOF is reached for a padding/unpadding cipher in DECRYPT mode, the the decryption result is unpadded. If EOF is encountered part-way through a block, an IllegalBlockSizeException is thrown.

When EOF is reached for a padding/unpadding cipher in ENCRYPT mode, the last block is padded before encryption. If the cipher does not support padding and the last block is incomplete, an IllegalBlockSizeException is thrown.

For stream ciphers, that is, ciphers capable of encrypting or decrypting a byte at a time, no buffering is necessary.

Note: calling methods of a cipher while it is being used by a CipherInputStream (apart from methods that have no side-effects, like getAlgorithm(), get*BlockSize(), etc.) will probably result in incorrect or unexpected output.

Copyright © 1997 Systemics Ltd on behalf of the Cryptix Development Team.
All rights reserved.

$Revision: 1.10 $

Since:
IJCE 1.0.0
Author:
David Hopwood, Raif S. Naffah
See Also:
java.security.Cipher, java.security.Cipher#getInputBlockSize, java.security.Cipher#getOutputBlockSize, java.security.CipherOutputStream

Fields inherited from class java.io.FilterInputStream
in
 
Constructor Summary
CipherInputStream(java.io.InputStream is, Cipher cipher)
          Constructs an input stream using a cipher that must be initialised for either encryption or decryption, that is, a cipher whose state is either ENCRYPT or DECRYPT.
 
Method Summary
 int available()
          Returns the number of bytes that can be guaranteed to be read from this input stream without blocking.
 void close()
          Closes the input stream.
 void mark(int readlimit)
          Does nothing, since this class does not support mark/reset.
 boolean markSupported()
          Tests if this input stream supports the mark and reset methods of InputStream, which it does not.
 int read()
          Returns the next encrypted or decrypted byte, depending on the cipher state.
 int read(byte[] out, int offset, int length)
          Fills up the specified bytes of the out array with the next len encrypted or decrypted bytes (depending on the cipher state).
 void reset()
          Always throws an IOException, since this class does not support mark/reset.
 long skip(long n)
          Skips over and discards n bytes of data from the input stream.
 
Methods inherited from class java.io.FilterInputStream
read
 
Methods inherited from class java.lang.Object
, clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

CipherInputStream

public CipherInputStream(java.io.InputStream is,
                         Cipher cipher)
Constructs an input stream using a cipher that must be initialised for either encryption or decryption, that is, a cipher whose state is either ENCRYPT or DECRYPT.
Parameters:
in - the input stream.
cipher - an initialised cipher.
Throws:
NullPointerException - if is == null || cipher == null
java.lang.IllegalStateException - if cipher.getState() == UNINITIALIZED
See Also:
java.security.Cipher
Method Detail

read

public int read(byte[] out,
                int offset,
                int length)
         throws java.io.IOException
Fills up the specified bytes of the out array with the next len encrypted or decrypted bytes (depending on the cipher state).
Overrides:
read in class java.io.FilterInputStream
Parameters:
out - the byte array into which the encrypted or decrypted bytes will be read.
offset - the offset into out indicating where the first encrypted or decrypted byte should be read.
length - the number of encrypted/decrypted bytes to read.
Returns:
the number of bytes read into out, or -1 if no encrypted or decrypted bytes remained.
Throws:
java.io.IOException - if an error occurs.
See Also:
java.security.Cipher#ENCRYPT, java.security.Cipher#DECRYPT, java.security.Cipher#getState

read

public int read()
         throws java.io.IOException
Returns the next encrypted or decrypted byte, depending on the cipher state.
Overrides:
read in class java.io.FilterInputStream
Returns:
the next encrypted or decrypted byte, or -1 if the last encrypted/decrypted byte was already returned.
Throws:
java.io.IOException - if an error occurs.
See Also:
java.security.Cipher#ENCRYPT, java.security.Cipher#DECRYPT, java.security.Cipher#getState

skip

public long skip(long n)
          throws java.io.IOException
Skips over and discards n bytes of data from the input stream. The skip method may, for a variety of reasons, end up skipping over some smaller number of bytes, possibly 0. The actual number of bytes skipped is returned.
Overrides:
skip in class java.io.FilterInputStream
Parameters:
n - the number of bytes to be skipped.
Returns:
the actual number of bytes skipped.
Throws:
java.io.IOException - if an I/O error occurs.

available

public int available()
              throws java.io.IOException
Returns the number of bytes that can be guaranteed to be read from this input stream without blocking.
Overrides:
available in class java.io.FilterInputStream
Throws:
java.io.IOException - if an I/O error occurs.

close

public void close()
           throws java.io.IOException
Closes the input stream.
Overrides:
close in class java.io.FilterInputStream
Throws:
java.io.IOException - if an error occurs.

mark

public void mark(int readlimit)
Does nothing, since this class does not support mark/reset.
Overrides:
mark in class java.io.FilterInputStream

reset

public void reset()
           throws java.io.IOException
Always throws an IOException, since this class does not support mark/reset.
Overrides:
reset in class java.io.FilterInputStream

markSupported

public boolean markSupported()
Tests if this input stream supports the mark and reset methods of InputStream, which it does not.
Overrides:
markSupported in class java.io.FilterInputStream
Returns:
false, since this class does not support the mark and reset methods.