2015-06-17 54 views
1

我知道aes加密需要在16個塊中,但我的印象是使用Cipher.getInstance("AES/ECB/PKCS5PADDING");填充字節數組來實現這一點。我的代碼如下:當使用aes/ecb/pkcs5padding解密字節數組時,IllegalBlockSizeException

CipherUtils.java

private static byte[] key = { 
     0x74, 0x68, 0x69, 0x73, 0x49, 0x73, 0x41, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b, 0x65, 0x79 
};//"thisIsASecretKey"; 

public static byte[] EncryptByteArray(byte[] array) 
{ 
    try 
    { 
     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); 
     SecretKeySpec secretKey = new SecretKeySpec(key, "AES"); 
     cipher.init(Cipher.ENCRYPT_MODE, secretKey); 

     return (cipher.doFinal(array)); 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 

    } 
    return null; 
} 

public static byte[] DecryptByteArray(byte[] array) 
{ 
    try 
    { 
     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); 
     SecretKeySpec secretKey = new SecretKeySpec(key, "AES"); 
     cipher.init(Cipher.DECRYPT_MODE, secretKey); 

     return cipher.doFinal(array); 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 

    } 
    return null; 
} 

主程序

 fis = new FileInputStream(path); 

     toDecrypt = new byte[fis.available()+1]; 

     int content; 
     int i = 0; 
     while ((content = fis.read()) != -1) { 

      // convert to byte and display it 
      toDecrypt[i] = (byte)content; 
      i += 1; 
     } 

     byte[] decryptedStr = CipherUtils.DecryptByteArray(toDecrypt); 

     FileOutputStream decryptedStream = new FileOutputStream(path); 
     decryptedStream.write (decryptedStr); 
     decryptedStream.close(); 

path該文件是使用在cipherutils.java的函數加密和寫入文件使用FileOutputStream.write

更新 - 我使用Gradle爲Android構建。

+1

首先用硬編碼輸入單元測試你的方法:加密它並解密結果應該導致輸出等於輸入。完成之後,您會意識到加密和解密工作正常,並且問題出在您編寫和讀取文件的方式。 available()不會返回文件的長度。即使這樣做,你的數組也包含一個額外的字節。所以這沒有意義。 –

+2

請不要使用ECB模式。它在語義上不安全。您應該至少使用CBC模式和隨機IV。充其量,你應該認證密文。這通常使用GCM等認證模式或通過HMAC運行密文(加密 - 然後MAC)來完成。 –

+0

...或運行* IV *和密文雖然HMAC ... –

回答

0

管理使用@ JonSkeet的回答些辦法(謝謝!):

 File file = new File(path); 
     fis = new FileInputStream(file); 

     toDecrypt = new byte[(int)file.length()]; 
     fis.read(toDecrypt); 

     byte[] decrypted = CipherUtils.DecryptByteArray(toDecrypt); 
     FileOutputStream decryptedStream = new FileOutputStream(bookPath); 
     decryptedStream.write (decrypted); 
     decryptedStream.close(); 

正如他指出的,我不應該使用available()方法。與迭代每個字節相比,還有更好的寫入文件的方式!根據評論,我也用隨機IV將加密更改爲CBC模式。

3

這就是問題所在:

toDecrypt = new byte[fis.available()+1]; 

首先,您使用的available()方法,這是從來沒有一個好主意。接下來,即使假設它返回的文件的長度,你加1它 - 爲什麼?你當然只需要文件中的字節。

做到這一點最簡單的方法就是使用Files.readAllBytes

byte[] toDecrypt = Files.readAllBytes(Paths.get(path)); 
// TODO: Change the method name to follow Java conventions 
byte[] decrypted = CipherUtils.DecryptByteArray(toDecrypt); 
Files.write(Paths.get(path), decrypted); 

現在,您不必擔心關閉文件流,要麼...(如果你已經設法將解密你可能不會能寫,因爲你仍然有打開的文件在當前的代碼讀取)

我還強烈建議重新訪問您異常「處理」:

  • C atching Exception幾乎總是一個壞主意
  • 調用e.printStackTrace(),然後繼續若無其事幾乎總是一個壞主意
+0

謝謝!我收到「錯誤:package java.nio.file不存在」,但我使用的是最新版本的Java。我使用的是Gradle 2.4,以及Android Tools插件1.2.0。對不起,我真的很陌生,大部分代碼都不是我自己的 - 我的老闆希望內部人員能夠使用Java! –

+0

@DomHarris:你在使用Android?您從未在問題中提及任何地方 - 這絕對會影響可用的內容... *請*包括髮布時的重要信息。 –

相關問題