我正在開發一個小程序,使用AES-256和HMAC來加密/解密二進制文件來檢查結果。多線程中的AES + HMAC加密 - Java
我的代碼是基於Java中AESCrypt實現,但我想修改它允許多個線程同時做這項工作。
我得到原始字節的大小,並計算每個線程的16字節塊的數量,然後我啓動線程並提供有關偏移量的信息以應用於讀取和寫入(因爲存在加密文件的標題,所以offset_write = offset_read + header_length)。
當它完成加密後,我通過輸出內容(無標題)通過HMAC生成校驗和。
問題是一些字節在兩個線程之間的字節中被破壞。
代碼的主:
//..
// Initialization and creation of iv, aesKey
//..
in = new FileInputStream(fromPath);
out = new FileOutputStream(toPath);
//..
// Some code for generate the header and write it to out
//..
double totalBytes = new Long(archivo.length()).doubleValue();
int bloquesHilo = new Double(Math.ceil(totalBytes/(AESCrypt.NUM_THREADS*AESCrypt.BLOCK_SIZE))).intValue();
int offset_write = new Long((out.getChannel()).position()).intValue();
for (int i = 0; i < AESCrypt.NUM_THREADS; i++)
{
int offset = bloquesHilo*AESCrypt.BLOCK_SIZE*i;
HiloCrypt hilo = new HiloCrypt(fromPath, toPath, ivSpec, aesKey, offset, offsetInicio, bloquesHilo, this);
hilo.start();
}
代碼線程(類HiloCrypt): 公共類HiloCrypt繼承Thread {
private RandomAccessFile in;
private RandomAccessFile out;
private Cipher cipher;
private Mac hmac;
private IvParameterSpec ivSpec2;
private SecretKeySpec aesKey2;
private Integer num_blocks;
private Integer offset_read;
private Integer offset_write;
private AESCrypt parent;
public HiloCrypt(String input, String output, IvParameterSpec ivSpec, SecretKeySpec aesKey, Integer offset_thread, Integer offset_write, Integer blocks, AESCrypt parent2)
{
try
{
// If i don't use RandomAccessFile there is a problem copying data
this.in = new RandomAccessFile(input, "r");
this.out = new RandomAccessFile(output, "rw");
int total_offset_write = offset_write + offset_thread;
// Adjust the offset for reading and writing
this.out.seek(total_offset_write);
this.in.seek(offset_thread);
this.ivSpec2 = ivSpec;
this.aesKey2 = aesKey;
this.cipher = Cipher.getInstance(AESCrypt.CRYPT_TRANS);
this.hmac = Mac.getInstance(AESCrypt.HMAC_ALG);
this.num_blocks = blocks;
this.offset_read = offset_thread;
this.offset_write = total_offset_write;
this.parent = parent2;
} catch (Exception e)
{
System.err.println(e);
return;
}
}
public void run()
{
int len, last,block_counter,total = 0;
byte[] text = new byte[AESCrypt.BLOCK_SIZE];
try{
// Start encryption objects
this.cipher.init(Cipher.ENCRYPT_MODE, this.aesKey2, this.ivSpec2);
this.hmac.init(new SecretKeySpec(this.aesKey2.getEncoded(), AESCrypt.HMAC_ALG));
while ((len = this.in.read(text)) > 0 && block_counter < this.num_blocks)
{
this.cipher.update(text, 0, AESCrypt.BLOCK_SIZE, text);
this.hmac.update(text);
// Write the block
this.out.write(text);
last = len;
total+=len;
block_counter++;
}
if (len < 0) // If it's the last block, calculate the HMAC
{
last &= 0x0f;
this.out.write(last);
this.out.seek(this.offset_write-this.offset_read);
while ((len = this.out.read(text)) > 0)
{
this.hmac.update(text);
}
// write last block of HMAC
text=this.hmac.doFinal();
this.out.write(text);
}
// Close streams
this.in.close();
this.out.close();
// Code to notify the end of the thread
}
catch(Exception e)
{
System.err.println("Hola!");
System.err.println(e);
}
}
}
有了這個代碼,如果我只能執行1個線程,加密/解密變得完美,但是如果使用2+線程,線程作業之間的區域中存在字節問題,那麼數據會在那裏損壞,並且校驗和也會失敗。
我想是因爲它得到接近2倍比一個快線與線要做到這一點,我想應該是因爲處理不被文件的訪問和。
作爲一個不相關的數據,它在MB Air上在43秒內壓縮250Mb的數據。 ¿這是個好時光?
不要打擾。多線程會讓事情變得更慢。多次讀取和寫入會減慢I/O,因爲文件操作在順序時最快。在HMAC操作之前必須重新組裝數據會浪費時間。 (你使用什麼鏈接模式?) –
這可能有很多原因。如果你關心表現,你應該試着弄清楚它們是什麼。 (數據是否已經在緩存中?您是否忘記按順序將數據提供給HMAC功能?您確定實際上處理了所有數據嗎?) –
@DavidSchwartz是的,我在最後一塊數據時依次輸入數據得到處理。它實際上並不檢查所有線程是否完成,但是通過調試信息,我可以確保所有線程都在我的測試中結束。 – odarriba