ch.ethz.ssh2.crypto.cipher.CipherInputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ganymed-ssh2 Show documentation
Show all versions of ganymed-ssh2 Show documentation
Ganymed SSH-2: Java based SSH-2 Protocol Implementation
The newest version!
/*
* Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
* Please refer to the LICENSE.txt for licensing details.
*/
package ch.ethz.ssh2.crypto.cipher;
import java.io.IOException;
import java.io.InputStream;
/**
* CipherInputStream.
*
* @author Christian Plattner
* @version $Id: CipherInputStream.java 11 2011-05-27 14:14:06Z [email protected] $
*/
public class CipherInputStream
{
BlockCipher currentCipher;
InputStream bi;
byte[] buffer;
byte[] enc;
int blockSize;
int pos;
/*
* We cannot use java.io.BufferedInputStream, since that is not available in
* J2ME. Everything could be improved alot here.
*/
private static final int BUFF_SIZE = 8192;
byte[] input_buffer = new byte[BUFF_SIZE];
int input_buffer_pos = 0;
int input_buffer_size = 0;
public CipherInputStream(BlockCipher tc, InputStream bi)
{
this.bi = bi;
changeCipher(tc);
}
private int fill_buffer() throws IOException
{
input_buffer_pos = 0;
input_buffer_size = 0;
input_buffer_size = bi.read(input_buffer, 0, BUFF_SIZE);
return input_buffer_size;
}
private int internal_read(byte[] b, int off, int len) throws IOException
{
if (input_buffer_size < 0)
{
return -1;
}
if (input_buffer_pos >= input_buffer_size)
{
if (fill_buffer() <= 0)
{
return -1;
}
}
int avail = input_buffer_size - input_buffer_pos;
int thiscopy = (len > avail) ? avail : len;
System.arraycopy(input_buffer, input_buffer_pos, b, off, thiscopy);
input_buffer_pos += thiscopy;
return thiscopy;
}
public void changeCipher(BlockCipher bc)
{
this.currentCipher = bc;
blockSize = bc.getBlockSize();
buffer = new byte[blockSize];
enc = new byte[blockSize];
pos = blockSize;
}
private void getBlock() throws IOException
{
int n = 0;
while (n < blockSize)
{
int len = internal_read(enc, n, blockSize - n);
if (len < 0)
{
throw new IOException("Cannot read full block, EOF reached.");
}
n += len;
}
try
{
currentCipher.transformBlock(enc, 0, buffer, 0);
}
catch (Exception e)
{
throw new IOException("Error while decrypting block.");
}
pos = 0;
}
public int read(byte[] dst) throws IOException
{
return read(dst, 0, dst.length);
}
public int read(byte[] dst, int off, int len) throws IOException
{
int count = 0;
while (len > 0)
{
if (pos >= blockSize)
{
getBlock();
}
int avail = blockSize - pos;
int copy = Math.min(avail, len);
System.arraycopy(buffer, pos, dst, off, copy);
pos += copy;
off += copy;
len -= copy;
count += copy;
}
return count;
}
public int read() throws IOException
{
if (pos >= blockSize)
{
getBlock();
}
return buffer[pos++] & 0xff;
}
public int readPlain(byte[] b, int off, int len) throws IOException
{
if (pos != blockSize)
{
throw new IOException("Cannot read plain since crypto buffer is not aligned.");
}
int n = 0;
while (n < len)
{
int cnt = internal_read(b, off + n, len - n);
if (cnt < 0)
{
throw new IOException("Cannot fill buffer, EOF reached.");
}
n += cnt;
}
return n;
}
}