diff src/ch/ethz/ssh2/crypto/cipher/CipherInputStream.java @ 273:91a31873c42a ganymed

start conversion from trilead to ganymed
author Carl Byington <carl@five-ten-sg.com>
date Fri, 18 Jul 2014 11:21:46 -0700
parents
children 071eccdff8ea
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ch/ethz/ssh2/crypto/cipher/CipherInputStream.java	Fri Jul 18 11:21:46 2014 -0700
@@ -0,0 +1,160 @@
+/*
+ * 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 dkocher@sudo.ch $
+ */
+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;
+	}
+}