2013-11-04 62 views
0

我試圖通過這種方式來我的文件加密:無法解密加密文件?

加密:

static void encrypt(String strInput , String strOutput) throws IOException, 
    NoSuchAlgorithmException,NoSuchPaddingException, InvalidKeyException { 
    FileInputStream fis = new FileInputStream(strInput); 
    FileOutputStream fos = new FileOutputStream(strOutput); 

    SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), 
      "AES"); 
    Cipher cipher = Cipher.getInstance("AES"); 
    cipher.init(Cipher.ENCRYPT_MODE, sks); 
    CipherOutputStream cos = new CipherOutputStream(fos, cipher); 
    int b; 
    byte[] d = new byte[8]; 
    while ((b = fis.read(d)) != -1) { 
     cos.write(d, 0, b); 
    } 
    // Flush and close streams. 
    cos.flush(); 
    cos.close(); 
    fis.close(); 
} 

和解密回:

解密:

static String decrypt(String strInput) throws IOException, NoSuchAlgorithmException, 
    NoSuchPaddingException, InvalidKeyException { 
    FileInputStream fis = new FileInputStream(strInput); 

    int endFile = strInput.length() - 4; 
    String strOut = strInput.substring(0, endFile) + "xx.jpg"; 

    FileOutputStream fos = new FileOutputStream(strOut); 

    SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), 
       "AES"); 
    Cipher cipher = Cipher.getInstance("AES"); 
    cipher.init(Cipher.DECRYPT_MODE, sks); 
    CipherInputStream cis = new CipherInputStream(fis, cipher); 
    int b; 
    byte[] d = new byte[8]; 

    while ((b = cis.read(d)) != -1) { 
     fos.write(d, 0, b); 
    } 
    fos.flush(); 
    fos.close(); 
    cis.close(); 
    return strOut; 
} 

然而,結果文件的大小是0 kb,當我嘗試t時roubleshoot b = cis.read(d)在解密,總是返回-1,也cis.available()總是返回0.任何人都可以告訴我我的代碼哪部分是錯誤的?

注:我可以確保將要解密的文件始終存在。

+0

這段代碼實際上在我的機器上工作。我們可以看到你調用的加密和解密代碼嗎?也許你打電話解密與錯誤的參數? – Francis

+0

嗯,不這麼認爲,因爲我只通過filePath加密和解密方法.. – Rendy

+0

Btw @Francis你也試過圖片嗎? – Rendy

回答

1

我認爲這個問題是因爲你試圖解密未加密的數據(或沒有正確加密)。

在您的decrypt()方法中,CipherOutputStream隱藏了Cipher類可能拋出的所有例外情況。見javadoc for CipherOutputStream

此外,這個類捕獲所有的祖先類不拋出的異常。

要揭露問題,您可能需要手動執行密碼使用。這裏有一個簡單的例子:

static String decrypt(String strInput) throws IOException, 
    NoSuchAlgorithmException, NoSuchPaddingException, 
    InvalidKeyException, IllegalBlockSizeException, BadPaddingException { 

    FileInputStream fis = new FileInputStream(strInput); 

    int endFile = strInput.length() - 4; 
    String strOut = strInput.substring(0, endFile) + "xx.txt"; 

    FileOutputStream fos = new FileOutputStream(strOut); 

    SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES"); 
    Cipher cipher = Cipher.getInstance("AES"); 
    cipher.init(Cipher.DECRYPT_MODE, sks); 

    int b; 
    byte[] d = new byte[8]; 
    while ((b = fis.read(d)) != -1) { 
     fos.write(cipher.update(d)); 
    } 
    fos.write(cipher.doFinal()); 

    fos.flush(); 
    fos.close(); 
    fis.close(); 
    return strOut; 
} 

你發佈在你的問題中的算法似乎對有效輸入工作正常。例如,假設突然想到了以下主要:

public static void main(String[] argv) { 
    try { 
     encrypt("test.txt", "XXX.txt"); 
     decrypt("XXX.txt"); 
    } 
    catch (Exception e) { 
     System.out.println(e); 
     e.printStackTrace(); 
    } 
} 

利用這一點,並用文本文件和JPG文件,完美執行你的算法,同時測試。但是,當使用解密算法的無效輸入時,那麼您描述的問題開​​始出現。

爲了進行測試,讓我們來想象我們做出試圖解密是明確的,像這樣(只是改變了main傳遞給decrypt()參數)文件「錯誤」:

encrypt("test.txt", "XXX.txt"); 
decrypt("test.txt"); 

隨後的當然,輸入到decrypt()方法的填充將是錯誤的,我們應該得到一個異常。

然而,使用您的decrypt()版本,沒有例外。我們得到的只是一個空文件。

使用修改後的版本FO是上面顯示我們得到以下異常decrypt()方法:

javax.crypto.BadPaddingException: Given final block not properly padded 
javax.crypto.BadPaddingException: Given final block not properly padded 
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811) 
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676) 
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313) 
    at javax.crypto.Cipher.doFinal(Cipher.java:1970) 
    at MainTest.decrypt(MainTest.java:71) 
    at MainTest.main(MainTest.java:21) 
+0

嗨弗朗西斯,我剛剛意識到我的加密圖像的大小是16字節。它應該是這樣嗎? – Rendy

+0

這聽起來不對。 AES作爲128位的固定塊大小,因此輸出總是應該是16個字節的因子。但是我非常懷疑你的圖像太小了(這意味着你的原始圖像的大小不到16字節)。雖然我不確定在Java 7安全提供程序中默認使用了哪些填充,但如果它是pkcs5或7(很可能),那麼即使是空白的輸入字符串也會創建一個16字節的加密輸出(填充) 。所以這可能意味着你的原始輸入是空的。 – Francis

+0

最後我發現我的錯誤!實際上,我設置的目標路徑與源路徑相同。所以這就是爲什麼它只給了16B(我想它只能讀取圖像的第一部分)。 – Rendy