java. 대용량 데이터의 암복호화

대용량 파일 등을 처리할 경우에
전체 데이터를 메모리에 로드하고 작업하는 것은 바람직하지 않고 많은 문제의 원인이 됩니다.

암복호화 처리시 순차적으로 필요한 블럭만을 메모리 로드하고 처리 후 해지하도록 해야 합니다.
특정 시점에 버퍼사이즈만큼의 메모리만을 할당하며 전체 데이터에 대해 순차적인 처리를 할 수 있는 암복호화 로직은 다음과 같이 작성할 수 있습니다.

public static String ALGORITHM = "AES";
public static String MODE = "ECB";
public static String PADDING = "PKCS5Padding";
private static final int BUFFER_SIZE = 1024;

public static long encrypt(
     InputStream inputStream,
     long inputStreamLength,
     OutputStream outputStream,
     byte[] key )throws Exception{

 SecretKeySpec secretKeySpec = new SecretKeySpec( key, ALGORITHM );
 javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance( ALGORITHM + "/" + MODE + "/" + PADDING );
 cipher.init( javax.crypto.Cipher.ENCRYPT_MODE, secretKeySpec );

 int readCnt = -1;
 long readTotal = 0;
 long writeTotal = 0;
 byte[] buffer = new byte[ BUFFER_SIZE ];
 while( ( readCnt = inputStream.read( buffer ) ) > -1 ){
  readTotal += readCnt;
  byte[] encBuffer = null;
  if( readCnt < BUFFER_SIZE || readTotal == inputStreamLength ){
   byte[] last = new byte[ readCnt ];
   System.arraycopy( buffer, 0, last, 0, readCnt );
   encBuffer = cipher.doFinal( last );
  }else{
   encBuffer = cipher.update( buffer );
  }
  outputStream.write( encBuffer, 0, encBuffer.length );
  writeTotal += encBuffer.length;
 }
 outputStream.flush();

 return writeTotal;

}

public static void decrypt(
     InputStream inputStream,
     long inputStreamLength,
     OutputStream outputStream,
     byte[] key )throws Exception{

 SecretKeySpec secretKeySpec = new SecretKeySpec( key, ALGORITHM );
 javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance( ALGORITHM + "/" + MODE + "/" + PADDING );
 cipher.init( javax.crypto.Cipher.DECRYPT_MODE, secretKeySpec );

 int readCnt = -1;
 long readTotal = 0;
 byte[] buffer = new byte[ BUFFER_SIZE ];
 while( ( readCnt = inputStream.read( buffer ) ) > -1 ){
  readTotal += readCnt;
  byte[] decBuffer = null;

  if( readCnt < BUFFER_SIZE || readTotal == inputStreamLength ){
   byte[] last = new byte[ readCnt ];
   System.arraycopy( buffer, 0, last, 0, readCnt );
   decBuffer = cipher.doFinal( last );
  }else{
   decBuffer = cipher.update( buffer );
  }
  outputStream.write( decBuffer, 0, decBuffer.length );
 }
 outputStream.flush();

}