2012-04-19 75 views
1

我們有它包裝BouncyCastle的(實際上SpongyCastle Android版)河豚來加密數據流的類:河豚代碼應該是等價的,但不是

public class BlowfishOutputStream extends OutputStream 
{ 
    private final OutputStream os; 
    private final PaddedBufferedBlockCipher bufferedCipher; 

我們原來的代碼寫入之前加密整個字節數組在單次操作

public void write(byte[] raw, int offset, int length) throws IOException 
{ 
    byte[] out = new byte[bufferedCipher.getOutputSize(length)]; 
    int result = this.bufferedCipher.processBytes(raw, 0, length, out, 0); 
    if (result > 0) 
    { 
     this.os.write(out, 0, result); 
    } 
} 

輸出流時發送圖像(一次即大數據量)它導致兩個拷貝被保持在存儲器中的一次。

下面的代碼是等價的,但不是,我不知道爲什麼。我可以驗證數據是否正在發送(總計c2相當於length),但是在我們的服務器上收到數據時,我們會在看到內容之前丟棄該圖像。我在這個階段所知道的是,當使用初始代碼時,接收到響應並且可以提取包含的圖像,當使用替換代碼時接收到響應(並被接受),但圖像看起來不被提取。

public void write(byte[] raw, int offset, int length) throws IOException 
{ 
    // write to the output stream as we encrypt, not all at once. 
    final byte[] inBuffer = new byte[Constants.ByteBufferSize]; 
    final byte[] outBuffer = new byte[Constants.ByteBufferSize]; 
    ByteArrayInputStream bis = new ByteArrayInputStream(raw); 
    // read into inBuffer, encrypt into outBuffer and write to output stream 
    for (int len; (len = bis.read(inBuffer)) != -1;) 
    { 
     int c2 = this.bufferedCipher.processBytes(inBuffer, 0, len, outBuffer, 0); 
     this.os.write(outBuffer, 0, c2); 
    } 
} 

注意,這個問題是不是由於缺少呼叫doFinal,當流被關閉,這就是所謂的。

public void close() throws IOException 
{ 
    byte[] out = new byte[bufferedCipher.getOutputSize(0)]; 
    int result = this.bufferedCipher.doFinal(out, 0); 
    if (result > 0) 
    { 
     this.os.write(out, 0, result); 
    } 
    *nb try/catch omitted* 
} 
+0

我想我有解決方案,其中第二算法不兌現'length'傳入,而是假定'raw'的全部是消息。現在測試。 – 2012-04-19 02:56:55

回答

2

證實,但具有諷刺意味的問題是不是與圖像,但在以前的數據,但這些數據是在寫完整raw字節數組,並指定不只是範圍。在飛行的字節數組加密等效代碼爲:

@Override 
public void write(byte[] raw, int offset, int length) throws IOException 
{ 
    // write to the stream as we encrypt, not all at once. 
    final byte[] inBuffer = new byte[Constants.ByteBufferSize]; 
    final byte[] outBuffer = new byte[Constants.ByteBufferSize]; 
    int readStart = offset; 
    // read into inBuffer, encrypt into outBuffer and write to output stream 
    while(readStart<length) 
    { 
     int readAmount = Math.min(length-readStart, inBuffer.length); 
     System.arraycopy(raw, readStart, inBuffer, 0, readAmount); 
     readStart+=readAmount; 
     int c2 = this.bufferedCipher.processBytes(inBuffer, 0, readAmount, outBuffer, 0); 
     this.os.write(outBuffer, 0, c2); 
    } 
} 
+0

,稍微好一點的是省略inBuffer並從'readStart'開始讀'raw',並使用'ByteBufferSize'而不是'inBuffer.length'。請注意,Android喜歡使用byte [8x1024](8k)緩衝區 – 2012-04-20 06:08:16