2016-05-16 12 views
0

Javaで非常に大規模な暗号化されたファイルからの読み込みに、私は次のコードを使用しています:ファイルも(非常に大きいと問題、Javaの

FileInputStream in = new FileInputStream("file.txt"); 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 

Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(saveLocation), "utf-8")); 

int read; 
byte buffer[] = new byte[16384]; 
byte getData[] = new byte[16384]; 

while((read = in.read(buffer)) != -1) 
{ 

baos.write(buffer, 0, read); 

Cipher cipher = Cipher.getInstance(symCipher); 
IvParameterSpec ivParameterSpec = new IvParameterSpec(initVecBytes); 
cipher.init(Cipher.DECRYPT_MODE, originalKey, ivParameterSpec); 
byte[] original = cipher.doFinal(baos.toByteArray()); 
String s = new String(original); 
writer.append(s); 
baos.reset(); 
} 

writer.close(); 

を大きなメモリを1つのメモリに読み込みます)私はそれを小さなバッファに読み込んだ後、小さなバイトのデータを暗号化し、最後にファイルに書き出します。

私はこれを行うときただし、データの一部が破損することになります。私はそれが正常に動作16kのではない小さいファイルを使用する場合

</AddressLine><_��SR����_�hEE</AddressLine></AddressLines><Postcode> 

、私は唯一の小さな得るように見えます新しい配列の読み込みの開始時に破損したデータの量は、次の配列が読み取られるまで再び正常になります。

これはなぜ正しく動作していないのですか?

+0

の5行は、 'symCipher'何ですか?ですか –

+2

このようなことを意味するストリームを使用しないのはなぜですか? CipherInputStreamとCipherOutputStreamが気になります。 'Cipher#update(byte)'メソッドを使うこともできます。 –

+1

'.init'を一回実行してから、必要に応じて最後の' .update'を除いて各バッファフルを実行し、 '.doFinal'の最後(空のもの)を' Cipher'のjavadocで説明したように実行する必要があります。また、 'BAOS'に書き込んだり、読み戻しするのは時間の無駄です。' .update'と '.doFinal'の両方は配列の範囲をとることができます。デフォルトのバイトコードを 'String'にデコードした後、バイトにエンコードする' Writer'に渡すと常にコストがかかり、デフォルトのcharsetが完全なシングルバイトコードである場合にのみ動作します。代わりにOutputStreamにバイトを書き込んでください。 ... –

答えて

1

ほとんどの暗号はステートフルなので、機能しません。具体的には、暗号ブロック連鎖モードでは、平文を前の暗号文ブロックとXORしなければならない。しかし、16kごとに、代わりにIVとXORします。解読操作の途中でCipherを再初期化することはできません。ここで

はコードto which EJP alluded.

Cipher cipher = Cipher.getInstance(symCipher); 
cipher.init(Cipher.DECRYPT_MODE, originalKey, new IvParameterSpec(initVecBytes)); 
try (InputStream in = Files.newInputStream(Paths.get("file.txt"))) { 
    Files.copy(new CipherInputStream(in, cipher), Paths.get(saveLocation)); 
} 
1
  1. ByteArrayOutputStreamWriterを取り除くとFileOutputStreamに直接復号化された配列を書きなさい。
  2. 暗号化と復号化の両方で、ファイル全体に同じCipherを使用し、読み取りごとに1回ではなく1回初期化します。
  3. CipherInputStreamで約5行のコードでこれを行うことができます。
+0

あまりにも細かい点を置かないでください: 'CipherInputStream' – erickson