view src/com/trilead/ssh2/crypto/cipher/CipherOutputStream.java @ 103:1a34365fab9b
merge
author |
Carl Byington <carl@five-ten-sg.com> |
date |
Tue, 17 Jun 2014 22:01:53 -0700 (2014-06-18) |
parents |
0ce5cc452d02 |
children |
|
line source
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);
}
}