2012-05-31 47 views
12

使用tomcat,我有兩個web應用程序,即app1和app2。我以加密的形式(使用下面的代碼)從app1發送url到app2。然後在app2 我解密了這個加密的url。但是在decryp方法的第50行得到異常。獲取javax.crypto.IllegalBlockSizeException:使用填充密碼解密時,輸入長度必須是16的倍數?

"Getting javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher" 

雖然爲了調試,當我嘗試解密(使用相同的代碼)加密的url在app1,它工作正常。但無法弄清楚在app2上導致這個異常的原因是什麼?

下面是代碼

import java.security.Key; 

import javax.crypto.Cipher; 
import javax.crypto.spec.SecretKeySpec; 

import sun.misc.BASE64Decoder; 
import sun.misc.BASE64Encoder; 

public class AESEncryptionDecryptionTest { 

    private static final String ALGORITHM  = "AES"; 
    private static final String myEncryptionKey = "ThisIsFoundation"; 
    private static final String UNICODE_FORMAT = "UTF8"; 

    public static String encrypt(String valueToEnc) throws Exception { 
     Key key = generateKey(); 
     Cipher c = Cipher.getInstance(ALGORITHM); 
     c.init(Cipher.ENCRYPT_MODE, key); 
     byte[] encValue = c.doFinal(valueToEnc.getBytes()); 
     String encryptedValue = new BASE64Encoder().encode(encValue); 
     return encryptedValue; 
    } 

public static String decrypt(String encryptedValue) throws Exception { 
    Key key = generateKey(); 
    Cipher c = Cipher.getInstance(ALGORITHM); 
    c.init(Cipher.DECRYPT_MODE, key); 
    byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedValue); 
    byte[] decValue = c.doFinal(decordedValue);//////////LINE 50 
    String decryptedValue = new String(decValue); 
    return decryptedValue; 
} 

private static Key generateKey() throws Exception { 
    byte[] keyAsBytes; 
    keyAsBytes = myEncryptionKey.getBytes(UNICODE_FORMAT); 
    Key key = new SecretKeySpec(keyAsBytes, ALGORITHM); 
    return key; 
} 

public static void main(String[] args) throws Exception { 

    String value = "password1"; 
    String valueEnc = AESEncryptionDecryptionTest.encrypt(value); 
    String valueDec = AESEncryptionDecryptionTest.decrypt(valueEnc); 

    System.out.println("Plain Text : " + value); 
    System.out.println("Encrypted : " + valueEnc); 
    System.out.println("Decrypted : " + valueDec); 
} 

} 
+0

見我答,並得到一些想法[這裏同樣的問題] [1] [1]:http://stackoverflow.com/questions/17234359/javax-crypto-illegalblocksizeexception -input-length-must-multiple-of-16-whe/21378212#21378212 希望能對你有所幫助。 – Krishna

回答

10

作品在我的機器上。如果您在將字節轉換爲字符串的每個實例中使用「UNICODE_FORMAT」,反之亦然,這有幫助嗎?此行可能是一個問題:

byte[] encValue = c.doFinal(valueToEnc.getBytes()); 

應該

byte[] encValue = c.doFinal(valueToEnc.getBytes(UNICODE_FORMAT)); 

無論如何,如果你使用「AES」的算法,並使用JCE,實際使用的將是「AES /算法ECB/PKCS5Padding」。除非您100%確定自己在做什麼,否則ECB不應該用於任何事情。我建議總是明確指定算法,以避免這種混淆。 「AES/CBC/PKCS5Padding」將是一個不錯的選擇。但要小心,使用任何合理的算法,您還必須提供和管理IV。

在加密密碼的情況下使用ECB密碼更加不理想,如果我正確解釋您的示例,這就是您使用加密進行的操作。您應該使用PKCS#5中爲此指定的基於密碼的加密,使用Java,這在SecretKeyFactory中爲您提供。請確保使用「PBKDF2WithHmacSHA1」具有足夠高的重複計數(任何範圍從〜5-20 000,取決於您的目標計算機)以使用密碼從中派生對稱密鑰。

如果它實際上是密碼存儲而不是密碼加密,那麼您可以使用相同的技術來實現。

+0

嗨浮雕。看起來它的發生becoz response.sendRedirect在app2接收時替換加密的URL中的一些字符?如果你可以看看http://stackoverflow.com/questions/10836902/response-sendredirect-replace-some-characters-in-encrypted- url-when-receiving-in時,這會很有幫助。我從昨天開始真的陷入了困境:( –

+0

答案沒錯,Base64不是網絡安全的,所以一般來說它不能用在網址中,而不會首先逃脫它;另一種更容易使用的方法來實現你的目標是使用十六進制編碼,它是開箱即用的網絡安全。 – emboss

+0

但是,請注意:如果它確實是您以這種方式作爲URL的一部分發送的密碼,那麼這根本就不安全。 - 在密碼字典的幫助下強制您的方式最多隻需要幾個小時... – emboss

-3

此錯誤表明您使用的選擇組合僅需要16個字符的源文本。 如果要加密密碼,可以將原始密碼截斷或填充爲16個字符以進行加密,並在解密後進行修剪。 這種方式必須限制真實密碼不超過16個字符,但您可以使用較長的使用密碼來混淆不應該知道您的密碼的人。

+4

不,它不表示您只能使用最多16個字符!答案顯然是錯誤的。 –

-1

當對密碼進行雙重解密時,我看到了這個錯誤(密碼通過就好像你在這裏所說的那樣)。請務必檢查您是否正在進行多次解密。 (我的錯誤是8的倍數,但我在那裏使用了不同的方案......)在我的情況下,當讀取文件時我解密,然後在填寫字段時再次解密。 (桌面應用程序)

相關問題