2013-07-10 35 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援助? –

相关问题