2011-04-08 26 views
2

如果我使用錯誤的鍵或錯誤的鹽進行解密BadPaddingException被拋出。 我期望一個不正確的字符串被返回。 的doFinal()導致異常的解密法AES BadPaddingException

消息:This is just an example

Unfug:'ΩÙΩ„SåF?V®ßs.k˚·ºç€èÀHfif∫ÙÉÕ

Exception in thread "main" javax.crypto.BadPaddingException: Given final block not properly padded 
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) 
    at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..) 
    at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..) 
    at javax.crypto.Cipher.doFinal(DashoA13*..) 
    at casino.AES.decryptString(AES.java:130) 
    at casino.AES.main(AES.java:172) 

 public static void main(String[] args) throws Exception { 
     //Encryption 
     AES encr = new AES(); 
     encr.setKey("KEY"); 
     encr.setSalt("SALT"); 
     encr.setup(); 
     String message = "This is just an example"; 
     System.out.println("Message : " + message); 



     byte[] code = encr.encrypt(message); 
     System.out.println("Encrypted Strinng : "+ new String(code, "UTF-8")); 

     //Decryption 
     AES dec = new AES(); 
     dec.setKey("INCORRECT"); //<--- incorrect 
     dec.setSalt("SALT"); 
     dec.setup(); 

     System.out.println(dec.decryptString(code)); 
    } 




     public synchronized void setKey(String key) throws UnsupportedEncodingException { 
     this.key = key.getBytes("UTF-8"); 
     isPasswordAlreadySet = true; 
    } 


    public synchronized void setSalt(String salt) throws UnsupportedEncodingException { 
     this.salt = salt.getBytes("UTF-8"); 
    } 

    public synchronized void setup() throws Exception { 
    MessageDigest digest = MessageDigest.getInstance("SHA-256"); 
    digest.update(key); 
    digest.update(salt); 
    byte[] raw = digest.digest(); 

    skeySpec = new SecretKeySpec(raw, "AES"); 
    cipher = Cipher.getInstance("AES"); 
    } 

public synchronized byte[] encrypt(byte[] klartext) throws Exception { 
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 

    byte[] encrypted = cipher.doFinal(klartext); 

    return encrypted; 
    } 

    public synchronized byte[] encrypt(String klartext) throws Exception{ 
    return encrypt(klartext.getBytes("UTF-8")); 
    } 






    public synchronized byte[] decrypt(byte[] code) throws Exception { 
    cipher.init(Cipher.DECRYPT_MODE, skeySpec); 
    byte[] original = cipher.doFinal(code); 
    return original; 
    } 

    public synchronized double decryptDouble(byte[] code) throws Exception { 
    cipher.init(Cipher.DECRYPT_MODE, skeySpec); 
    byte[] original = cipher.doFinal(code); 
    return doubleFromBytes(original); 
    } 

謝謝! 弗雷德裏克

回答

3

你應該或者使用AES與隱式填充聲明(見the available modes)或強制的長度(以字節爲單位)的加密/解密數據的,要作16

另外的倍數,在默認情況下,JAVA使用ECB模式,根據您使用的數據類型,這可能確實不安全,您應該使用CBC模式。

+0

我已經改變了密碼的initline在一個提供者無關的方式的密鑰:密碼= Cipher.getInstance( 「AES/CBC/PKCS5Padding」); 但是拋出同樣的異常。 爲了獲得正確的長度,我使用了SHA-Hash - 我認爲這應該足夠了。 此外,我第一次使用setup()方法時不會引發異常 – Frederik 2011-04-08 15:28:21

+3

@Frederik:您必須瞭解填充的工作方式:填充模式將在加密之前將一些填充內容附加到純文本數據。解密後,該填充再次被剝離。但要知道有多少個字節需要去除,填充的內容很重要,如果我們使用錯誤的密鑰解密,最後一些字節不是將被填充算法添加的格式之一。如上所述,使用'NoPadding',但是您必須確保您的數據長度是塊長度的倍數。 – 2011-04-08 15:49:48

+0

對於'PKCS5Padding',它與DES CBC的[RFC 1423](http://tools.ietf.org/html/rfc1423#section-1.1)中描述的相同。 – 2011-04-08 15:57:51

6

填充是一個很好的健全性檢查。假設解密不正確的數據是均勻分佈的,那麼對於每255個不正確的密碼,它將只顯示爲正確的PKCS5/PKCS7填充約1次。 (1/256 + 1/256^2 + 1/256^3 ...)

所以這很有幫助,但它不是你應該依賴的東西---實際上幾乎是8位的消息摘要並不是對數據完整性的充分測試。還有一件事:如果攻擊者可以反覆更改密文並讓你解密它(例如可能是存儲在cookie中的加密數據),並且它們能夠區分你的行爲,當解密的數據拋出異常時對於不好的填充,當它只是垃圾時,他們可以通過「填充oracle攻擊」來確定明文。順便說一下,如果你真的想要想要你所期望的行爲,你可以使用「AES/CTR/NoPadding」,它不需要一個確切的塊大小,並且總是會返回一個解密的字節[],不管是或者不是鑰匙匹配。

相關問題