2016-12-01 4 views
0

チャンクファイル解読は、ファイルの先頭に初期化ベクトルが追加され、その後に暗号化されたデータが追加されるように実装されました。以下の復号化方法は、ファイルを復号化し、書き込み:Android NでAES復号化の動作が変更されました

private void decrypt_AES_CBC_PKCS7(final byte[] symKeyBytes, final FileInputStream inputStream, final FileOutputStream outputStream) throws Exception { 

    Security.addProvider(new BouncyCastleProvider()); 

    // Read init vector 
    final byte[] iv = new byte[16]; 
    inputStream.read(iv, 0, 16); 

    // Prepare for decryption 
    final SecretKeySpec secretKeySpec = new SecretKeySpec(symKeyBytes, "AES"); 
    final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", new BouncyCastleProvider()); 
    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv)); 

    // Decrypt chunk by chunk 
    int chunkLen = 0; 
    final byte[] buffer = new byte[CHUNK_SIZE_DECRTPY]; // CHUNK_SIZE_DECRTPY = 20 * 1024 * 1024; 

    while ((chunkLen = inputStream.read(buffer)) > 0) { 

     byte[] decrypted = cipher.doFinal(buffer, 0, chunkLen); 

     outputStream.write(decrypted, 0, decrypted.length); 
    } 

    // close streams 
    inputStream.close(); 
    outputStream.close(); 
} 

コードは以前のAndroidのバージョン(L & M)でうまくいきましたが、私たちは、Android Nとネクサス5X上でそれをしようとしたとき、16「ジャンク」バイトが挿入されました結果として生じるファイルの開始時に。これは、1つのチャンクのみで構成されるファイルでのみ発生します。つまり、1つのチャンクよりも大きなサイズのファイルが正しく復号化され、余分なバイトが前に付加されることはありません。興味深いことに、Androidスタジオデバッガを接続してコードを実行すると、IVの読み込みと入力ストリームの読み込みの間にブレークポイントがあり、解読が正常に機能し、出力ファイルに余分なバイトが表示されません。

例暗号化されたファイル(IV、すなわち、最初の行、最初の16のバイトとして表示されている):

Example encrypted file

例は、最初の16バイトのみのAndroid Nに追加され、ファイルを解読:

Example decrypted file

すべての提案は大歓迎です!

+0

サンプルが16進数の場合、「ジャンク」バイトは助けになりません.IV、クリアデータ、暗号化データ、不正な復号化データを含めてください。 – zaph

+0

@zaphのご提案ありがとうございます。 – kivesic

+2

'inputStream.read(iv、0、16)'の返された 'int'値をチェックして、実際に16バイト(それ以下)を読み取っていないことを確認してはいけませんか? – martijno

答えて

0

@martijnoによって示唆されるように、私はinputStream.read(iv, 0, 16)の結果をチェックし、それは私がIVを読み取るコードの一部変更、それの最初の呼び出しが返す-1アンドロイドN.そうで判明:

final byte[] iv = new byte[16]; 
int result; 
int numTries = 0; 
int MAX_NUM_TRIES = 2; 

do { 
    result = inputStream.read(iv, 0, 16); 
    ++numTries; 
} while (result == -1 && numTries < MAX_NUM_TRIES); 

if (result == -1) { 
    throw new Exception("Failed to read IV from file!"); 
} 

IVを読み込む2回の試行で十分ですが、Android Nのデバイスが増えればさらにテストします。

関連する問題