Mercurial > 510Connectbot
view src/ch/ethz/ssh2/crypto/cipher/CipherInputStream.java @ 434:7ea898484623
Added tag stable-1.9.1 for changeset 3e25a713555d
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Mon, 09 Mar 2015 16:33:11 -0700 |
parents | 071eccdff8ea |
children |
line wrap: on
line source
/* * 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; } }