CipherInputStream.java :  » App » seasprint » com » trilead » ssh2 » crypto » cipher » Android Open Source

Android Open Source » App » seasprint 
seasprint » com » trilead » ssh2 » crypto » cipher » CipherInputStream.java

package com.trilead.ssh2.crypto.cipher;

import java.io.IOException;
import java.io.InputStream;

/**
 * CipherInputStream.
 * 
 * @author Christian Plattner, plattner@trilead.com
 * @version $Id: CipherInputStream.java,v 1.1 2007/10/15 12:49:55 cplattne Exp $
 */
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.
   */

  final int BUFF_SIZE = 2048;
  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 = 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;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.