2013-04-03 76 views
2

我一直在Java版本的BouncyCastle的加密API中徘徊。我對PaddedBufferedBlockCipher類有點困惑。我理解(可能是錯誤的),它的目的是逐步處理加密,即從數據讀取文件。如何正確使用bouncycastle的PaddedBufferedBlockCipher?

當我調用processBytes()一次,提供所有的數據立即加密,然後doFinal()它按預期工作。但是,當我多次調用processBytes時,使用適當的偏移量/長度,意圖以較小的塊進行處理,然後執行doFinal(),則失敗。任何人都可以解釋爲什麼以下代碼失敗?假設clearText是64字節長,並且加密是以4 x 16字節的塊執行的,則這些值是硬編碼的。

byte[] key= Hex.decode("a4ea1a7227e032c37f5635e70ba1bd38a4ea1a7227e032c37f5635e70ba1bd38"); 
byte[] iv= Hex.decode("a4ea1a7227e032c37f5635e70ba1bd38"); 
byte[] clearText= Hex.decode("28d3966905e33c063e7b74c7c7dcb2d688d48d53101d2a6901d365146faf0c9cde3da9ef37664a5e32e4e468f9b52f587d76b78caaf9d9823dd9eb2c1d700d7c"); 

BlockCipher bc = new AESFastEngine(); 
CBCBlockCipher cipher = new CBCBlockCipher(bc); 
PaddedBufferedBlockCipher mode = new PaddedBufferedBlockCipher(cipher); 
KeyParameter kp = new KeyParameter(key); 
CipherParameters ivAndKey= new ParametersWithIV(kp, iv); 
mode.init(true, ivAndKey); 

byte[] outBuf = new byte[mode.getOutputSize(clearText.length)]; 

int blockSize = mode.getBlockSize(); 

// process the 64 bytes of clearText, in 4 x 16-byte chunks 
for (int i = 0; i < 4; i++) { 

    mode.processBytes(clearText, i * blockSize, blockSize, outBuf, i * blockSize); 
} 

try { 
    // call doFinal on the last block (bytes 48->64) 
    mode.doFinal(outBuf, 48); 
} catch (Exception e){} 

System.out.println(new String(Hex.encode(outBuf))); 

預期輸出是:fe391ed41650f3b344ed3d200ffa3c55e71b1d97dbd91c0fbdd0989c3a48822e7e5230e9d6d073bc0752436d9bea9f26328a11586a290e712fbbf874ddfd4ba14e28600e55c7d6ac69467693320a82d3

但我得到的結果是: 00000000000000000000000000000000fe391ed41650f3b344ed3d200ffa3c55e71b1d97dbd91c0fbdd0989c3a48822e328a11586a290e712fbbf874ddfd4ba14e28600e55c7d6ac69467693320a82d3

編輯

修改後的代碼按PeterDettman的建議:

int bytesProcessed = 0; 

for (int i = 0; i < 4; i++) { 
      // Fixed to be '+=' 
    bytesProcessed += mode.processBytes(clearText, i * blockSize, blockSize, outBuf, bytesProcessed); 
} 

mode.doFinal(outBuf, bytesProcessed); 

回答

3

至於如何修復代碼:該processBytes方法返回它寫到輸出的實際金額,所以你需要跟蹤的outbuf的位置,並添加爲每個呼叫返回長度(對於doFinal也是如此)。請注意,您不應該在內部承擔任何特定的緩衝區大小,或者是否立即或延遲地刷新「全部」緩衝區。

至於爲什麼:在解密的情況下,填充模式不能輸出一個塊,直到它知道是否有更多的塊來(因爲它會從最後的塊中刪除填充)。所以它被迫關於輸出塊的「懶惰」。對於加密來說,情況並非如此,但我認爲,processBytes的代碼的簡單性/一致性同樣如此。

+0

我曾嘗試過,但仍然沒有運氣。所有的例子發現在線處理* processBytes的一次調用中的所有*數據(我覺得奇怪,考慮到類的性質)。我是否理解processBytes()中'outOff'的值應該從0開始,然後用每次調用processBytes()返回的值遞增更新?返回的processedBytes的數量是否也會影響輸入數組(inOff)的偏移量?我更新了我的代碼(以上)以反映您的建議(按照我的理解),但沒有運氣。我究竟做錯了什麼? – hunter

+0

是的,從0開始並逐步更新 - 嘗試'bytesProcessed + = mode.processBytes(...)'(注意** + = **)。 –

+0

這樣做 - 謝謝你的時間。 – hunter