2012-09-28 13 views
9

私はCipherInputStreamとCipherOutputStreamを使用してAESを使用してファイルを暗号化しています。CipherInputStreamのみ16バイト(AES/Java)を読み取る

encrypt(...)は正常に動作しているようですが、私のdecrypt(...)関数は自分のファイルの最初の16バイトを復号化するだけです。ここで

は私のクラスである:decrypt関数は、最初の16バイトのみを読んで、なぜ

public class AESFiles { 

    private byte[] getKeyBytes(final byte[] key) throws Exception { 
     byte[] keyBytes = new byte[16]; 
     System.arraycopy(key, 0, keyBytes, 0, Math.min(key.length, keyBytes.length)); 
     return keyBytes; 
    } 

    public Cipher getCipherEncrypt(final byte[] key) throws Exception { 
     byte[] keyBytes = getKeyBytes(key); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES"); 
     IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes); 
     cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); 
     return cipher; 
    } 

    public Cipher getCipherDecrypt(byte[] key) throws Exception { 
     byte[] keyBytes = getKeyBytes(key); 
     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES"); 
     IvParameterSpec ivParameterSpec = new IvParameterSpec(keyBytes); 
     cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); 
     return cipher; 
    } 

    public void encrypt(File inputFile, File outputFile, byte[] key) throws Exception { 
     Cipher cipher = getCipherEncrypt(key); 
     FileOutputStream fos = null; 
     CipherOutputStream cos = null; 
     FileInputStream fis = null; 
     try { 
      fis = new FileInputStream(inputFile); 
      fos = new FileOutputStream(outputFile); 
      cos = new CipherOutputStream(fos, cipher); 
      byte[] data = new byte[1024]; 
      int read = fis.read(data); 
      while (read != -1) { 
       cos.write(data, 0, read); 
       read = fis.read(data); 
       System.out.println(new String(data, "UTF-8").trim()); 
      } 
      cos.flush(); 
     } finally { 
      fos.close(); 
      cos.close(); 
      fis.close(); 
     } 
    } 

    public void decrypt(File inputFile, File outputFile, byte[] key) throws Exception { 
     Cipher cipher = getCipherDecrypt(key); 
     FileOutputStream fos = null; 
     CipherInputStream cis = null; 
     FileInputStream fis = null; 
     try { 
      fis = new FileInputStream(inputFile); 
      cis = new CipherInputStream(fis, cipher); 
      fos = new FileOutputStream(outputFile); 
      byte[] data = new byte[1024]; 
      int read = cis.read(data); 
      while (read != -1) { 
       fos.write(data, 0, read); 
       read = cis.read(data); 
       System.out.println(new String(data, "UTF-8").trim()); 
      } 
     } finally { 
      fos.close(); 
      cis.close(); 
      fis.close(); 
     } 
    } 

    public static void main(String args[]) throws Exception { 
     byte[] key = "mykey".getBytes("UTF-8"); 
     new AESFiles().encrypt(new File("C:\\Tests\\secure.txt"), new File("C:\\Tests\\secure.txt.aes"), key); 
     new AESFiles().decrypt(new File("C:\\Tests\\secure.txt.aes"), new File("C:\\Tests\\secure.txt.1"), key); 
    } 
} 

は、だから私の質問は、ありますか?

+0

16バイトしか復号化しないことをどう知っていますか?投稿を編集して、取得している例外を表示できますか? – Gray

+0

私は例外を取得していません。ファイル "secure.txt.1"(復号化されたファイル)のサイズは16バイトしかなく、ソースは41バイトです。 – Joshua

+0

'CipherInputStream'を使うことは、カーペットの下で例外を掃除するので非常に扱いにくいことに注意してください(それはそれらを隠すことを意味する諺です)。私は自分でそれを使用しません。 –

答えて

12

これは非常に微妙です。あなたの問題は、fosの前にcosを閉じることです。その暗号化された出力の最後のパディングブロックが出力ファイルに書き込まれることは決してありませんCipherOutputStream下からFileOutputStreamを閉じ

} finally { 
    fos.close(); 
    cos.close(); 
    fis.close(); 
} 

を:何をやっているあなたのencrypt(...)方法で。 fosの後に閉じると、cosコードが正常に動作するはずです。

本当に、あなたのような何かを検討する必要があります。

FileOutputStream fos = null; 
    CipherOutputStream cos = null; 
    FileInputStream fis = null; 
    try { 
     fis = new FileInputStream(inputFile); 
     fos = new FileOutputStream(outputFile); 
     cos = new CipherOutputStream(fos, cipher); 
     // once cos wraps the fos, you should set it to null 
     fos = null; 
     ... 
    } finally { 
     if (cos != null) { 
      cos.close(); 
     } 
     if (fos != null) { 
      fos.close(); 
     } 
     if (fis != null) { 
      fis.close(); 
     } 
    } 

FYI:org.apache.commons.io.IOUtilsnullチェックを処理し、あなたのための例外をキャッチ素晴らしい​​方法があります。

+0

うわー!本当にありがとう!!! – Joshua

+0

とてもいい解決策です。 –

+1

これは、try-with-resourcesを使って処理できます。 'try'ステートメントに複数のストリームを指定することができます。これは自動的に閉じられ、もちろん - 右(逆)の順序で閉じられます。 –

関連する問題