2017-01-19 6 views
0

私は最近、ファイルの暗号化/解読に取り組んでいます。アンドロイドAES解読ファイル:BadPaddingException:EVP_CipherFinal_ex

BadPaddingException:EVP_CipherFinal_ex:同じ鍵でファイルを復号しようとすると、常に発生します。

コードスニペットは以下に掲載されます。

何か間違っていますか?

ご協力いただきありがとうございます。

暗号化

public static void encryptFile() { 
    File file = new File(Environment.getExternalStorageDirectory().getPath() + "/" + TARGET_FILE); 

    FileInputStream fileInputStream; 
    FileOutputStream fileOutputStream; 

    byte[] buffer = new byte[1024 * 8]; 

    IvParameterSpec ivParameterSpec = new IvParameterSpec("123456789".getBytes()); 

    byte[] key = "only for testing".getBytes(); 
    MessageDigest sha; 
    try { 
     sha = MessageDigest.getInstance("SHA-1"); 
     key = sha.digest(key); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } 
    key = Arrays.copyOf(key, 16); // use only first 128 bit 

    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); 

    try { 
     fileInputStream = new FileInputStream(file); 
     fileOutputStream = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/" + ENCRYPT_FILE); 

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); 

     //CipherOutputStream cipherOutputStream = new CipherOutputStream(fileOutputStream, cipher); 

     int read; 

     while ((read = fileInputStream.read(buffer)) > 0) { 
      Log.i(TAG, "encrypt read= " + read); 

      byte[] encryptedData = cipher.doFinal(buffer); 
      if (encryptedData != null) { 
       Log.i(TAG, "encrypted size= " + encryptedData.length); 
       fileOutputStream.write(encryptedData, 0, read); 
      } 

      //cipherOutputStream.write(buffer, 0, buffer.length); 
     } 
     //cipherOutputStream.flush(); 
     //cipherOutputStream.close(); 
     fileInputStream.close(); 
     fileOutputStream.close(); 

    } catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException 
      | IllegalBlockSizeException | BadPaddingException 
      | InvalidAlgorithmParameterException | InvalidKeyException e) { 
     e.printStackTrace(); 
    } 
} 

復号化

public static void decryptFile() { 
    File file = new File(Environment.getExternalStorageDirectory().getPath() + "/" + ENCRYPT_FILE); 

    FileInputStream fileInputStream; 
    FileOutputStream fileOutputStream; 

    byte[] buffer = new byte[1024 * 8]; 

    IvParameterSpec ivParameterSpec = new IvParameterSpec("123456789".getBytes()); 

    byte[] key = "only for testing".getBytes(); 
    MessageDigest sha; 
    try { 
     sha = MessageDigest.getInstance("SHA-1"); 
     key = sha.digest(key); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
    } 
    key = Arrays.copyOf(key, 16); // use only first 128 bit 

    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); 

    try { 
     fileInputStream = new FileInputStream(file); 
     fileOutputStream = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/" + DECRYPT_FILE); 

     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
     cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); 

     //CipherInputStream cipherInputStream = new CipherInputStream(fileInputStream, cipher); 

     int read; 

     while ((read = fileInputStream.read(buffer)) > 0) { 
      Log.i(TAG, "decrypt read= " + read); 

      byte[] decryptedData = cipher.doFinal(buffer); 
      if (decryptedData != null) { 
       Log.i(TAG, "decrypted size= " + decryptedData.length); 
       fileOutputStream.write(decryptedData, 0, read); 
      } 

      //fileOutputStream.write(buffer, 0, buffer.length); 
     } 
     fileOutputStream.flush(); 
     fileOutputStream.close(); 
     //cipherInputStream.close(); 
     fileInputStream.close(); 

    } catch (IOException | NoSuchAlgorithmException | NoSuchPaddingException 
      | IllegalBlockSizeException | BadPaddingException 
      | InvalidAlgorithmParameterException | InvalidKeyException e) { 
     e.printStackTrace(); 
    } 
} 

ところで:私はでCipherInputStream/CipherOutStreamを使用するとき、それが正常に動作します。 FileInputStream/FileOutputStreamだけを使用することが可能かどうかを知りたいですか?ありがとうございました。

編集: 暗号化機能では約16バイトのバイト配列が拡大されますが、私は復号化のバッファサイズを増やしてみましたが、まだそれを動作させることはできません。

byte[] buffer = new byte[1024 * 8 + 16]; 

ログイン:

I /#_:com.android.org.conscrypt.NativeCrypto.EVP_CipherFinal_exでEVP_CipherFinal_ex

(:= 8208

javax.crypto.BadPaddingExceptionを読んで解読ネイティブメソッド)

at com.android.org.conscrypt.OpenSSLCipher.doFinalInternal(OpenSSLCipher.java:430)

CryptoHelper.decryptFileでjavax.crypto.Cipher.doFinal(Cipher.java:1340)

(AT com.android.org.conscrypt.OpenSSLCipher.engineDoFinal(OpenSSLCipher.java:466)

CryptoHelper.java:128)

編集ここでは、私が行ったのと同じ問題に遭遇した人のための#ロバートの答えに基づいてコードを更新します。

暗号化:

int read; 

     while ((read = fileInputStream.read(buffer)) > 0) { 
      Log.i(TAG, "encrypt read= " + read); 
      byte[] encryptedData = cipher.update(buffer, 0, read); 
      //byte[] encryptedData = cipher.doFinal(buffer); 
      if (encryptedData != null) { 
       Log.i(TAG, "encrypted size= " + encryptedData.length); 
       fileOutputStream.write(encryptedData, 0, encryptedData.length); 
      } 

      //cipherOutputStream.write(buffer, 0, buffer.length); 
     } 
     byte[] finals = cipher.doFinal(); 
     Log.i(TAG, "encrypted finals = " + finals.length); 
     fileOutputStream.write(finals, 0, finals.length); 

復号化:

int read; 

     while ((read = fileInputStream.read(buffer)) > 0) { 
      Log.i(TAG, "decrypt read= " + read); 

      //byte[] decryptedData = cipher.doFinal(buffer); 
      byte[] decryptedData = cipher.update(buffer, 0, read); 
      if (decryptedData != null) { 
       Log.i(TAG, "decrypted size= " + decryptedData.length); 
       fileOutputStream.write(decryptedData, 0, decryptedData.length); 
      } 

      //fileOutputStream.write(buffer, 0, buffer.length); 
     } 
     byte[] finals = cipher.doFinal(); 
     Log.i(TAG, "decrypted finals = " + finals.length); 
     fileOutputStream.write(finals, 0, finals.length); 

おかげで再びロバートの助けを。

答えて

3

問題があるのは、それぞれのブロックがパディングされるため、間違ったデータブロックごとに常にcipher.doFinal()と呼んでいるということです。

ブロック単位でデータを暗号化/復号化する場合、最後のブロックが処理された後でcipher.update(...)を使用する場合は、cipher.doFinal()を一度だけ呼び出してください。

簡単な方法は、CipherInputStream/CipherOutputStreamを使用することです。これは、私があなたのために記述したものです(ストリームを閉じるときにdoFinalが呼び出されます)。

+0

私はあなたの答えに従って、コードを編集しました。それは今働く。あなたの助けを大変感謝します。あなたは私の一日を救った。 – Youxian

関連する問題