大きいサイズのファイルの暗号化

先日の AES暗号化、複合の為に書いたメソッドはあまり現実的でない。
InputStream と OutputStream を渡す方が使いやすい。
書き直すと。。

import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
 * AESCriptor
 */

public final class AESCriptor{
   private Key secretKey;
   private AlgorithmParameterSpec ivParamSpec;
   /**
    * Constructor
    * @param key 256-bit or 128-bit
    * @param iv 16byte Initialize Vector
    */

   public AESCriptor(byte key,byte iv){
      secretKey = new SecretKeySpec(key,"AES");
      ivParamSpec = new IvParameterSpec(iv);
   }
   public void encrypt(final InputStream instream, OutputStream outstream){
      try{
         final PipedOutputStream po = new PipedOutputStream();
         PipedInputStream pin = new PipedInputStream();
         pin.connect(po);

         new Thread(new Runnable(){
            @Override
            public void run(){
               try{
                  byte buffer = new byte[1024];
                  int len;
                  while((len=instream.read(buffer,0,buffer.length)) >= 0){
                     po.write(buffer,0,len);
                     po.flush();

                  }
                  po.close();
                  instream.close();
               }catch(Exception e){
                  throw new RuntimeException(e);
               }
            }
         }).start();
         Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
         cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParamSpec);
         CipherOutputStream cout = new CipherOutputStream(
outstream, cipher);
         outstream.write(cipher.getIV());

         byte
 buffer = new byte[1024];
         int len;
         while*1 >= 0){
            cout.write(buffer,0,len);
            cout.flush();
         }
         cout.close();
         pin.close();
      }catch(Exception e){
         throw new RuntimeException(e);
      }
   }

   public void decrypt(final InputStream instream, OutputStream outstream){
      try{
         final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
         cipher.init(Cipher.DECRYPT_MODE,this.secretKey,this.ivParamSpec);
         final CipherInputStream cin =  new CipherInputStream(
instream, cipher);
         final PipedOutputStream po = new PipedOutputStream();
         PipedInputStream pin = new PipedInputStream();
         pin.connect(po);

         new Thread(new Runnable(){
            @Override
            public void run(){
               try{
                  int blocksize = cipher.getBlockSize();
                  for(int i=0;i < blocksize;i++) cin.read();

                  byte buffer = new byte[1024];
                  int len;
                  while((len=cin.read(buffer,0,buffer.length)) >= 0){
                     po.write(buffer,0,len);
                     po.flush();

                  }
                  po.close();
                  instream.close();
               }catch(Exception e){
                  throw new RuntimeException(e);
               }
            }
         }).start();
         byte
 buffer = new byte[1024];
         int len;
         while*2 >= 0){
            outstream.write(buffer,0,len);
            outstream.flush();
         }
         outstream.close();
         pin.close();
      }catch(Exception e){
         throw new RuntimeException(e);
      }
   }
}

*1:len=pin.read(buffer,0,buffer.length

*2:len=pin.read(buffer,0,buffer.length