2016-05-08 16 views
4

javaで単純な暗号化/復号化ツールを実装したいと思います。 私は小さいチュートリアルを見つけました:http://www.codejava.net/coding/file-encryption-and-decryption-simple-exampleJavaのAES解読 - 埋め込みに関する問題

大きなファイルの暗号化を保証するために、いくつかのコード行を変更しました。 今私は、復号化がうまくいかないという問題を抱えています。私は次のエラーメッセージ/例外だ

Error encrypting/decrypting file 
    at Algorithmus.Encryptor.doCrypto(Encryptor.java:71) 
    at Algorithmus.Encryptor.decrypt(Encryptor.java:39) 
    at GUI.MainWindow$encryptThread.run(MainWindow.java:838) 
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded 
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966) 
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824) 
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436) 
    at javax.crypto.Cipher.doFinal(Cipher.java:2165) 
    at Algorithmus.Encryptor.doCrypto(Encryptor.java:60) 
    ... 2 more 

を私はAES/CBC/PKCS5PaddingにTransoformationパラメータを変更しようとしましたが、それは効果がありません。誰もが、どのように与えられたコードを最適化するか知っていますか?

 private static final String ALGORITHM = "AES"; 

     private static final String TRANSFORMATION = "AES"; 

     public static void encrypt(String key, File inputFile, File outputFile) 
       throws ExtendedException { 
      doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile); 
     } 

     public static void decrypt(String key, File inputFile, File outputFile) 
       throws ExtendedException { 
      doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile); 
     } 

     private static void doCrypto(int cipherMode, String key, File inputFile, 
       File outputFile) throws ExtendedException { 
      try { 
       Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM); 
       Cipher cipher = Cipher.getInstance(TRANSFORMATION); 
       cipher.init(cipherMode, secretKey); 

       FileInputStream inputStream = new FileInputStream(inputFile); 


       CipherOutputStream out = new CipherOutputStream(new FileOutputStream(outputFile), cipher); 
       byte[] buffer = new byte[8192]; 
       byte[] outputBytes = null; 
       FileOutputStream outputStream = new FileOutputStream(outputFile); 
       int count; 
       while ((count = inputStream.read(buffer)) > 0) 
       { 
        out.write(buffer, 0, count); 
        outputBytes = cipher.doFinal(buffer); 

       } 


       inputStream.close(); 
       outputStream.close(); 

      } catch (NoSuchPaddingException | NoSuchAlgorithmException 
        | InvalidKeyException | BadPaddingException 
        | IllegalBlockSizeException | IOException ex) { 
       throw new ExtendedException("Error encrypting/decrypting file", ex); 
      } 
     } 

答えて

3

CipherOutputStreamを使用してください。 cipher.doFinal(buffer)を起動せず、出力ストリームを閉じることを忘れないでください。

FileInputStream inputStream = new FileInputStream(inputFile); 
FileOutputStream fileout = new FileOutputStream(outputFile); 
CipherOutputStream out = new CipherOutputStream(fileout , cipher); 

try { 
    byte[] buffer = new byte[8192]; 
    int count; 

    while ((count = inputStream.read(buffer)) > 0) { 
     out.write(buffer, 0, count); 
    } 
} finally { 
    out.close(); 
    inputStream.close(); 
} 

CipherOutputStreamは暗号を管理します。ストリームが閉じられ、内部バッファがフラッシュされると、doFinalが呼び出されます。

+0

ありがとうございます。それは完全に動作します!しかし、間違ったパスプライスを入力すると、例外はスローされません。復号化されたファイルは作成されますが、人間にとっては読めません。 – jollepe

+1

@jollepe暗号化されたデータのMACを追加してAESを使用する必要がある場合、AES/CBCによる暗号化は正しいパスワードの認証を行いません/ GCM。悪い埋め込みのエラーをユーザーに返すことは避けるか、攻撃者がパディングオラクル攻撃で攻撃者を悪用する可能性があります。 – zaph

関連する問題