| BlowfishOutputStream |
package BlowfishJ;
import java.io.*;
import java.util.*;
/**
* An OutputStream that encrypts data using the Blowfish algorithm.
* 30 Mar 2002, fixed bug in flush method
* @author Dale Anson (danson@germane-software.com), February, 2002
*/
public class BlowfishOutputStream extends OutputStream {
private OutputStream _out;
private String _passphrase;
private BlowfishCBC _cbc;
private long _iv;
byte[] _in_buffer;
byte [] _out_buffer;
int _bytes_in_buffer = 0;
boolean _started = false;
/**
* @param passphrase the password to use to encrypt the data
* @param os the OutputStream to write the data to
*/
public BlowfishOutputStream( String passphrase, OutputStream os ) {
_passphrase = passphrase;
_out = os;
// swiped from BlowfishEasy
// hash down the password to a 160bit key
SHA1 hasher = new SHA1();
hasher.update( _passphrase );
hasher.finalize();
// setup the encryptor (use a dummy IV)
_cbc = new BlowfishCBC( hasher.getDigest(), 0 );
hasher.clear();
_iv = new Random().nextLong();
_in_buffer = new byte[ BlowfishCBC.BLOCKSIZE ];
_out_buffer = new byte[ BlowfishCBC.BLOCKSIZE ];
}
/**
* Writes the specified byte to this output stream. The general contract for write
* is that one byte is written to the output stream. The byte to be written is
* the eight low-order bits of the argument b. The 24 high-order bits of b are
* ignored.
* @param b the byte to write
*/
public void write( int b ) throws IOException {
// make sure the iv is written to output stream -- this is always the
// first 8 bytes written out.
if ( !_started ) {
byte[] iv_bytes = new byte[ BlowfishCBC.BLOCKSIZE ];
BinConverter.longToByteArray( _iv, iv_bytes, 0 );
_out.write( iv_bytes, 0, iv_bytes.length );
_cbc.setCBCIV( _iv );
_started = true;
}
// if buffer isn't full, just store the input
++_bytes_in_buffer;
if ( _bytes_in_buffer < _in_buffer.length ) {
_in_buffer[ _bytes_in_buffer - 1 ] = ( byte ) b;
return ;
}
// else this input will fill the buffer
_in_buffer[ _bytes_in_buffer - 1 ] = ( byte ) b;
_bytes_in_buffer = 0;
// encrypt the buffer
_cbc.encrypt( _in_buffer, _out_buffer );
// write the out_buffer to the wrapped output stream
for ( int i = 0; i < _out_buffer.length; i++ ) {
_out.write( ( byte ) _out_buffer[ i ] );
}
return ;
}
/**
* This method calls flush(), so there is no need to call both.
* @see java.io.InputStream
*/
public void close() throws IOException {
// This output stream always writes out even blocks of 8 bytes. If it
// happens that the last block does not have 8 bytes, then the block will
// be padded to have 8 bytes.
// The last byte is ALWAYS the number of pad bytes and will ALWAYS be a
// number between 1 and 8, inclusive. If this means adding
// an extra block just for the pad count, then so be it.
// Minor correction: 8 isn't the magic number, rather it's BlowfishECB.BLOCKSIZE.
byte pad_val = ( byte ) ( _in_buffer.length - _bytes_in_buffer );
if ( pad_val > 0 ) {
while ( _bytes_in_buffer < _in_buffer.length ) {
_in_buffer[ _bytes_in_buffer ] = pad_val;
++ _bytes_in_buffer;
}
// encrypt the buffer
_cbc.encrypt( _in_buffer, _out_buffer );
// write the out_buffer to the wrapped output stream
for ( int i = 0; i < _out_buffer.length; i++ ) {
_out.write( ( byte ) _out_buffer[ i ] );
}
}
flush();
_out.close();
_cbc.cleanUp();
return ;
}
/**
* Flushes this output stream and causes any buffered bytes to be written.
*/
public void flush() throws IOException {
_out.flush();
return ;
}
}
| BlowfishOutputStream |