2013-07-10 65 views
6

在我的應用程序中,我使用secretKey加密和解密數據。爲此,我正在使用AES算法。但我在解密中得到了異常,三個已經使用密鑰加密的值中的一個值。非法塊大小異常在使用填充密碼解密時,輸入長度必須是16的倍數

的例外是:

Illegal Block Size Exception Input length must be multiple of 16 when decrypting with padded cipher. 

下面是我的代碼:

功能來encyrpt值

public static String symmetricEncrypt(String text, String secretKey) { 
    BASE64Decoder decoder = new BASE64Decoder(); 
    byte[] raw; 
    String encryptedString; 
    SecretKeySpec skeySpec; 
    BASE64Encoder bASE64Encoder = new BASE64Encoder(); 
    byte[] encryptText = text.getBytes(); 
    Cipher cipher; 
    try { 
     raw = decoder.decodeBuffer(secretKey); 
     skeySpec = new SecretKeySpec(raw, "AES"); 
     cipher = Cipher.getInstance("AES"); 
     cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
     encryptedString = bASE64Encoder.encode(cipher.doFinal(encryptText)); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
     return "Error"; 
    } 
    return encryptedString; 
} 

功能解密值

public static String symmetricDecrypt(String text, String secretKey) { 
    BASE64Decoder decoder = new BASE64Decoder(); 
    BASE64Decoder base64Decoder = new BASE64Decoder(); 
    Cipher cipher; 
    String encryptedString; 
    byte[] encryptText = null; 
    byte[] raw; 
    SecretKeySpec skeySpec; 
    try { 
     raw = decoder.decodeBuffer(secretKey); 
     skeySpec = new SecretKeySpec(raw, "AES"); 
     encryptText = base64Decoder.decodeBuffer(text); 
     cipher = Cipher.getInstance("AES"); 
     cipher.init(Cipher.DECRYPT_MODE, skeySpec); 
     encryptedString = new String(cipher.doFinal(encryptText)); 
    } catch (Exception e) { 
     e.printStackTrace(); 
     return "Error"; 
    } 
    return encryptedString; 
} 

下面是我在加密和解密

String secretKey = "XMzDdG4D03CKm2IxIWQw7g=="; 
String value1= "ABCD"; 
String enctypedValue1= "3uweh4pzoVyH1uODQmVNJA=="; 
String enctypedValue2= "37PTC20w4DMZYjG3f+GWepSvAbEJUccMXwS/lXilLav1qM/PrCTdontw5/82OdC1zzyhDEsFVRGo rV6gXAQcm+Zai15hliiUQ8l8KRMtUl4="; 
String value4= "20000"; 

/** Ecnryption and decryption of value1 **/ 
String encryptedValue1= symmetricEncrypt(value1, secretKey); 
String decryptedValue1 = symmetricDecrypt(encryptedValue1, secretKey); 

/** Decryption of enctypedValue1 **/ 
String decryptedValue2 = symmetricDecrypt(enctypedValue1, secretKey); 
System.out.println(decryptedValue2); 

/** Decryption of enctypedValue2 (Not decrypted)**/ 
String decryptedValue3 = symmetricDecrypt(enctypedValue2, secretKey); 
System.out.println(decryptedValue3); 

/** Ecnryption and decryption of value4 **/ 
String encryptedValue4= symmetricEncrypt(value4, secretKey); 
String decryptedValue4 = symmetricDecrypt(encryptedValue4, secretKey); 

在測試函數的值,我寫了下面的三個測試用例。

  1. 使用密鑰對新值(值1)進行加密和解密。
  2. 兩個使用相同密鑰解密的示例加密值(enctypedValue1,enctypedValue2)。 encryptedValue2在使用相同密鑰解密時出現問題。
  3. 使用密鑰加密和解密的新值(值4)。

在解密encryptedValue2我得到以下異常:

Illegal Block Size Exception Input length must be multiple of 16 when decrypting with padded cipher 

以下是我所得到的至今。

  1. 有問題的值在解碼時似乎有問題,它返回81長度數組,它無法解密?

  2. 如果這個問題發生了,它應該發生在所有的值上。

  3. 這是一個價值特定的問題,或者它是與填充有關的東西,或者它可以在不同的瀏覽器,不同的操作系統上有不同的行爲?

+2

,你使用'密碼=密碼。getInstance(「AES/ECB/PKCS5Padding」);'但是,在你的加密方法中,你使用了'cipher = Cipher.getInstance(「AES」);'。他們需要是一樣的。使用加密方法將填充添加到密碼中。 – Multithreader

+0

此鏈接可能會有所幫助:http://stackoverflow.com/questions/7640463/encryptionexception-javax-crypto-illegalblocksizeexception-input-length-must-b –

+0

@Multithreader感謝您的更正。其實它寫錯了。請參閱編輯的問題。 – RAS

回答

11

我能夠沒有任何問題地運行代碼。但是,我使用Apache的Base64進行編碼/解碼...也許你的Base64有錯誤。如果你自己寫的話,你很有可能錯過了一些案例。對於真正的生產代碼,請使用經過嚴格測試的庫,例如Apache's。

,可以看到我用的Base64這裏的圖書館:http://commons.apache.org/proper/commons-codec/download_codec.cgi

以下是完整的工作代碼:

package security.symmatric; 

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

    import org.apache.commons.codec.binary.Base64; 

    public class AES { 
     public static String symmetricEncrypt(String text, String secretKey) { 
      byte[] raw; 
      String encryptedString; 
      SecretKeySpec skeySpec; 
      byte[] encryptText = text.getBytes(); 
      Cipher cipher; 
      try { 
       raw = Base64.decodeBase64(secretKey); 
       skeySpec = new SecretKeySpec(raw, "AES"); 
       cipher = Cipher.getInstance("AES"); 
       cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
       encryptedString = Base64.encodeBase64String(cipher.doFinal(encryptText)); 
      } 
      catch (Exception e) { 
       e.printStackTrace(); 
       return "Error"; 
      } 
      return encryptedString; 
     } 

     public static String symmetricDecrypt(String text, String secretKey) { 
      Cipher cipher; 
      String encryptedString; 
      byte[] encryptText = null; 
      byte[] raw; 
      SecretKeySpec skeySpec; 
      try { 
       raw = Base64.decodeBase64(secretKey); 
       skeySpec = new SecretKeySpec(raw, "AES"); 
       encryptText = Base64.decodeBase64(text); 
       cipher = Cipher.getInstance("AES"); 
       cipher.init(Cipher.DECRYPT_MODE, skeySpec); 
       encryptedString = new String(cipher.doFinal(encryptText)); 
      } catch (Exception e) { 
       e.printStackTrace(); 
       return "Error"; 
      } 
      return encryptedString; 
     } 

     public static void main(String[] args) { 
      String secretKey = "XMzDdG4D03CKm2IxIWQw7g=="; 
      String value1= "ABCD"; 
      String enctypedValue1= "3uweh4pzoVyH1uODQmVNJA=="; 
      String enctypedValue2= "37PTC20w4DMZYjG3f+GWepSvAbEJUccMXwS/lXilLav1qM/PrCTdontw5/82OdC1zzyhDEsFVRGo rV6gXAQcm+Zai15hliiUQ8l8KRMtUl4="; 
      String value4= "20000"; 

      /** Ecnryption and decryption of value1 **/ 
      String encryptedValue1= symmetricEncrypt(value1, secretKey); 
      String decryptedValue1 = symmetricDecrypt(encryptedValue1, secretKey); 
      System.out.println(decryptedValue1); 

      /** Decryption of enctypedValue1 **/ 
      String decryptedValue2 = symmetricDecrypt(enctypedValue1, secretKey); 
      System.out.println(decryptedValue2); 

      /** Decryption of enctypedValue2 **/ 
      String decryptedValue3 = symmetricDecrypt(enctypedValue2, secretKey); 
      System.out.println(decryptedValue3); 

      /** Ecnryption and decryption of value4 **/ 
      String encryptedValue4= symmetricEncrypt(value4, secretKey); 
      String decryptedValue4 = symmetricDecrypt(encryptedValue4, secretKey); 
      System.out.println(decryptedValue4); 
     } 
    } 
在您的解密方法
+0

謝謝你的工作。我使用的是Sun的Base64。我想問一下Apache的Base64和Sun的Base64有什麼區別?我應該用我的程序中的Apache Base64替換它嗎? – JankiPanwala

+2

是的,我強烈推薦使用Apache的。儘量避免不惜一切代價使用Sun的庫。爲什麼?因爲他們的庫僅在Sun內部使用(未公開爲「公共API」)。因此,他們可以更改API,打破向後兼容性,並在任何時候停止支持API,而無需另行通知。至少,我明白... – Multithreader

+0

此代碼從主要方法工作正常,但不是當我寫在小程序類內。給予調用目標exception.Any援助? –

相關問題