blob: cf0db4afb411a8c66828f051adf699da75158879 [file] [log] [blame]
package com.trilead.ssh2.crypto.cipher;
import java.io.IOException;
import java.io.OutputStream;
/**
* CipherOutputStream.
*
* @author Christian Plattner, plattner@trilead.com
* @version $Id: CipherOutputStream.java,v 1.1 2007/10/15 12:49:55 cplattne Exp $
*/
public class CipherOutputStream
{
BlockCipher currentCipher;
OutputStream bo;
byte[] buffer;
byte[] enc;
int blockSize;
int pos;
/*
* We cannot use java.io.BufferedOutputStream, since that is not available
* in J2ME. Everything could be improved here alot.
*/
final int BUFF_SIZE = 2048;
byte[] out_buffer = new byte[BUFF_SIZE];
int out_buffer_pos = 0;
public CipherOutputStream(BlockCipher tc, OutputStream bo)
{
this.bo = bo;
changeCipher(tc);
}
private void internal_write(byte[] src, int off, int len) throws IOException
{
while (len > 0)
{
int space = BUFF_SIZE - out_buffer_pos;
int copy = (len > space) ? space : len;
System.arraycopy(src, off, out_buffer, out_buffer_pos, copy);
off += copy;
out_buffer_pos += copy;
len -= copy;
if (out_buffer_pos >= BUFF_SIZE)
{
bo.write(out_buffer, 0, BUFF_SIZE);
out_buffer_pos = 0;
}
}
}
private void internal_write(int b) throws IOException
{
out_buffer[out_buffer_pos++] = (byte) b;
if (out_buffer_pos >= BUFF_SIZE)
{
bo.write(out_buffer, 0, BUFF_SIZE);
out_buffer_pos = 0;
}
}
public void flush() throws IOException
{
if (pos != 0)
throw new IOException("FATAL: cannot flush since crypto buffer is not aligned.");
if (out_buffer_pos > 0)
{
bo.write(out_buffer, 0, out_buffer_pos);
out_buffer_pos = 0;
}
bo.flush();
}
public void changeCipher(BlockCipher bc)
{
this.currentCipher = bc;
blockSize = bc.getBlockSize();
buffer = new byte[blockSize];
enc = new byte[blockSize];
pos = 0;
}
private void writeBlock() throws IOException
{
try
{
currentCipher.transformBlock(buffer, 0, enc, 0);
}
catch (Exception e)
{
throw (IOException) new IOException("Error while decrypting block.").initCause(e);
}
internal_write(enc, 0, blockSize);
pos = 0;
}
public void write(byte[] src, int off, int len) throws IOException
{
while (len > 0)
{
int avail = blockSize - pos;
int copy = Math.min(avail, len);
System.arraycopy(src, off, buffer, pos, copy);
pos += copy;
off += copy;
len -= copy;
if (pos >= blockSize)
writeBlock();
}
}
public void write(int b) throws IOException
{
buffer[pos++] = (byte) b;
if (pos >= blockSize)
writeBlock();
}
public void writePlain(int b) throws IOException
{
if (pos != 0)
throw new IOException("Cannot write plain since crypto buffer is not aligned.");
internal_write(b);
}
public void writePlain(byte[] b, int off, int len) throws IOException
{
if (pos != 0)
throw new IOException("Cannot write plain since crypto buffer is not aligned.");
internal_write(b, off, len);
}
}