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.