The CipherOutputStream
Class
This class is a FilterOutputStream
that encrypts
or decrypts the data passing through it. It is composed of an OutputStream
,
or one of its subclasses, and a Cipher
. CipherOutputStream
represents a secure output stream into which a Cipher object has been
interposed. The write
methods of CipherOutputStream
first process the data with the embedded Cipher object before writing
it out to the underlying OutputStream. The Cipher object must be fully
initialized before being used by a CipherOutputStream.
For example, if the embedded Cipher has been initialized for encryption, the CipherOutputStream will encrypt its data, before writing them out to the underlying output stream.
This class adheres strictly to the semantics, especially the failure
semantics, of its ancestor classes java.io.OutputStream
and java.io.FilterOutputStream
.
This class has exactly those methods specified in its ancestor classes,
and overrides them all, so that all data is additionally processed
by the embedded cipher. Moreover, this class catches all exceptions
that are not thrown by its ancestor classes.
If you use this class, do not to 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 CipherOutputStream.
As an example of its usage, suppose cipher1
has
been initialized for encryption. The following code demonstrates how
to use a CipherOutputStream containing that cipher and a FileOutputStream
to encrypt data to be written to an output stream:
FileInputStream fis;
FileOutputStream fos;
CipherOutputStream cos;
fis = new FileInputStream("/tmp/a.txt");
fos = new FileOutputStream("/tmp/b.txt");
cos = new CipherOutputStream(fos, cipher1);
byte[] b = new byte[8];
int i = fis.read(b);
while (i != -1) {
cos.write(b, 0, i);
i = fis.read(b);
}
cos.flush();
This program reads the content from the file /tmp/a.txt
,
then encrypts and stores the result (the encrypted bytes) in /tmp/b.txt
.
The following example demonstrates how to easily connect several
instances of CipherOutputStream and FileOutputStream. In this example,
assume that cipher1
and cipher2
have
been initialized for decryption and encryption (with corresponding
keys), respectively:
FileInputStream fis;
FileOutputStream fos;
CipherOutputStream cos1, cos2;
fis = new FileInputStream("/tmp/a.txt");
fos = new FileOutputStream("/tmp/b.txt");
cos1 = new CipherOutputStream(fos, cipher1);
cos2 = new CipherOutputStream(cos1, cipher2);
byte[] b = new byte[8];
int i = fis.read(b);
while (i != -1) {
cos2.write(b, 0, i);
i = fis.read(b);
}
cos2.flush();
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
before it is written to /tmp/b.txt
.
There is one important difference between the flush
and close
methods
of this class, which becomes even more relevant if the encapsulated
Cipher object implements a block cipher algorithm with padding turned
on:
flush
flushes the underlying OutputStream by forcing any buffered output bytes that have already been processed by the encapsulated Cipher object to be written out. Any bytes buffered by the encapsulated Cipher object and waiting to be processed by it will not be written out.close
closes the underlying OutputStream and releases any system resources associated with it. It invokes thedoFinal
method of the encapsulated Cipher object, causing any bytes buffered by it to be processed and written out to the underlying stream by calling itsflush
method.