2009-08-04 80 views
8

我正在使用Java Cipher和AES實現加密/解密。除了在調用doFinal()時寫入5個額外的字節之外,一切都運行良好。所以,我最終得到了一個正確解碼的字符串,並附加了5個額外的字節。Java cipher.doFinal()寫入額外字節

我相信原因是整個16字節的塊正在寫入。我看到寫了3個16字節塊,包括最後一個。輸入的加密文件是64字節。未加密的文本應該是43個字節。

doFinal的文檔指出它可以返回寫入輸出緩衝區的字節數。但是,這是0,16,16,16。我已經嘗試過所有形式的doFinal並更新並且不會改變行爲。

這是有道理的,它寫出一個完整的塊,因爲這就是大多數這些算法的操作。但是,如果它不會告訴我輸出數據的大小,我該如何防止超額數據?

也許我應該使用另一種算法? AES256是一項要求,但我想知道是否有不同的塊類型或填充類型可能允許它寫入正確的字節數。

任何指導?

剪斷的(一些)簡潔:解密程序的

decryptCipher = Cipher.getInstance("AES"); 
decryptCipher.init(Cipher.DECRYPT_MODE, aesKey); 

業務的一部分。

long bytesToRead = inputFile.length(); 

    while ((inLen = in.read(buffer)) > 0) { 
     int bytesOut = 0; 
     byte[] cryptBytes = null; 
     int outLen = cipher.getOutputSize(inLen); 
     cryptBytes = new byte[outLen]; 

     if (bytesToRead <= buffer.length) { 
      try { 
       bytesOut = cipher.doFinal(buffer, 0, inLen, cryptBytes, 0); 
      } catch (ShortBufferException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } else 
      try { 
       bytesOut = cipher.update(buffer, 0, inLen, cryptBytes, 0); 
      } catch (ShortBufferException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     out.write(cryptBytes, 0, bytesOut); 
     bytesToRead -= inLen; 

    } 
    try { 
     out.flush(); 
     in.close(); 
     out.close(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

回答

14

當您調用Cipher.getInstance()時,您必須指定填充機制 - 顯然它在加密和解密時都必須相同。例如:

decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

沒有填充機制,解密端沒有關於明文末尾在哪裏(在最後一個塊內)的信息。

1

AES是分組密碼,自然它會給予你整個街區,如將所有的分組密碼。

查看Wikipedia article on AES瞭解更多信息。

你說你希望它輸出「正確的字節數」。你怎麼決定什麼是正確的字節數?

+1

我想他知道AES會這樣做,問題是關於如何使用Java API。 – skaffman 2009-08-04 07:39:19

+0

爲了在解密後知道正確的未加密大小,他應該將原始大小寫出到流中。 – 2009-08-04 07:45:24