Mercurial > 510Connectbot
diff app/src/main/java/ch/ethz/ssh2/crypto/cipher/CipherInputStream.java @ 438:d29cce60f393
migrate from Eclipse to Android Studio
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Thu, 03 Dec 2015 11:23:55 -0800 |
parents | src/ch/ethz/ssh2/crypto/cipher/CipherInputStream.java@071eccdff8ea |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/main/java/ch/ethz/ssh2/crypto/cipher/CipherInputStream.java Thu Dec 03 11:23:55 2015 -0800 @@ -0,0 +1,146 @@ +/* + * 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; + } +}