The CipherInputStream Class

This class is a FilterInputStream that encrypts or decrypts the data passing through it. It is composed of an InputStream, or one of its subclasses, and a Cipher. CipherInputStream represents a secure input stream into which a Cipher object has been interposed. The read methods of CipherInputStream return data that are read from the underlying InputStream but have additionally been processed by the embedded Cipher object. The Cipher object must be fully initialized before being used by a CipherInputStream.

For example, if the embedded Cipher has been initialized for decryption, the CipherInputStream will attempt to decrypt the data it reads from the underlying InputStream before returning it to the application.

This class adheres strictly to the semantics, especially the failure semantics, of its ancestor classes java.io.FilterInputStream and java.io.InputStream. This class has exactly those methods specified in its ancestor classes, and overrides them all, so that the data is additonally processed by the embedded cipher. Moreover, this class catches all exceptions that are not thrown by its ancestor classes. In particular, the skip(long) method skips only data that has been processed by the Cipher.

If you use this class, do not use methods that are not defined or that are overridden in this class (such as a new method or constructor that is later added to one of the super classes), because the design and implementation of those methods are unlikely to have considered security impact with regard to CipherInputStream.

As an example of its usage, suppose cipher1 has been initialized for encryption. The following code demonstrates how to use a CipherInputStream containing that cipher and a FileInputStream to encrypt input stream data:

 FileInputStream fis;
 FileOutputStream fos;
 CipherInputStream cis;

 fis = new FileInputStream("/tmp/a.txt");
 cis = new CipherInputStream(fis, cipher1);
 fos = new FileOutputStream("/tmp/b.txt");
 byte[] b = new byte[8];
 int i = cis.read(b);
 while (i != -1) {
 fos.write(b, 0, i);
 i = cis.read(b);
 }

This program reads and encrypts the content from the file /tmp/a.txt and then stores the result (the encrypted bytes) in /tmp/b.txt.

The following example demonstrates how to easily connect several instances of CipherInputStream and FileInputStream. In this example, assume that cipher1 and cipher2 have been initialized for encryption and decryption (with corresponding keys), respectively.

 FileInputStream fis;
 FileOutputStream fos;
 CipherInputStream cis1, cis2;

 fis = new FileInputStream("/tmp/a.txt");
 cis1 = new CipherInputStream(fis, cipher1);
 cis2 = new CipherInputStream(cis1, cipher2);
 fos = new FileOutputStream("/tmp/b.txt");
 byte[] b = new byte[8];
 int i = cis2.read(b);
 while (i != -1) {
 fos.write(b, 0, i);
 i = cis2.read(b);
 }

This program copies the content from file /tmp/a.txt to /tmp/b.txt, except that the content is first encrypted and then decrypted back when it is read from /tmp/a.txt. Of course because this program simply encrypts text and decrypts it back straight away, it is actually not very useful except as a simple way of illustrating chaining of CipherInputStreams.