javax.crypto。IllegalBlockSizeException:输入长度必须是16的倍数时,用填充密码解密?

时间:2021-12-04 15:33:57

Using tomcat, I have two web-applications i.e app1 and app2. I sent url from app1 in encrypted form (using below code) to app2 . Then at app2 I decrypted this encrypted url. But am getting below exception at line 50 of decryp method.

使用tomcat,我有两个web应用程序I。e app1和app2。我以加密的形式(使用下面的代码)将url从app1发送到app2。然后在app2我解密了这个加密的url。但是我在解密方法的第50行得到了下面的异常。

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

Though for debugging when I try to decrypt(using same code) the encrypted url at app1, it works fine. But not able to figure out what causing this exception at app2?

虽然在我试图解密(使用相同的代码)时进行调试,但在app1上的加密url可以正常工作。但是无法弄清楚是什么原因导致app2上的异常?

Here is the code

这是代码

 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);
}

}

3 个解决方案

#1


10  

Works on my machine. Does it help if you use `UNICODE_FORMAT' in every instance where you transform bytes to Strings and vice versa? This line could be a problem:

在我的机器上工作。如果在每个实例中都使用“UNICODE_FORMAT”将字节转换为字符串,反之亦然,这是否会有所帮助?这条线可能是个问题:

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

should be

应该是

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

Anyway, if you use "AES" as the algorithm and you use the JCE, the algorithm actually being used will be "AES/ECB/PKCS5Padding". Unless you are 100% sure about what you are doing, ECB shouldn't be used for anything. I'd recommend to always specify the algorithm explicitly in order to avoid such confusion. "AES/CBC/PKCS5Padding" would be a good choice. But watch out, with any reasonable algorithm you will also have to provide and manage an IV.

无论如何,如果你使用"AES"作为算法,你使用JCE,实际使用的算法将是"AES/ECB/PKCS5Padding。除非你百分之百确定自己在做什么,否则欧洲央行不应该被用来做任何事情。为了避免这种混淆,我建议始终明确地指定算法。“AES/CBC/PKCS5Padding(简称为AES)”是个不错的选择。但要小心,任何合理的算法你也必须提供和管理一个IV。

Using an ECB cipher is even less desirable in the context of encrypting passwords, which is what you seem to be doing with your encryption if I interpret your example correctly. You should use password-based encryption as specified in PKCS#5 for that purpose, in Java this is provided for you in SecretKeyFactory. Be sure to use "PBKDF2WithHmacSHA1" with a high enough iteration count (anything ranging from ~ 5-20 000, depends on your target machine) for using passwords to derive symmetric keys from them.

在加密密码的上下文中,使用欧洲央行密码甚至更不可取,如果我正确地解释了您的示例,您似乎正在使用您的加密。您应该在PKCS#5中为该目的使用基于密码的加密,在Java中,这是在SecretKeyFactory中为您提供的。确保使用“PBKDF2WithHmacSHA1”具有足够高的迭代计数(任何值在5- 20,000之间,取决于您的目标计算机)来使用密码从它们派生对称密钥。

The same technique can be used if it is actually password storage instead of password encryption what you are trying to achieve.

如果实际上是密码存储而不是密码加密,也可以使用相同的技术。

#2


-1  

I was seeing this error (with the password getting through just fine like you say here) when double-decrypting a value. Be sure to check to see if you are doing the decrypting more than once. (mine was multiple of 8 in the error, but I was using a different scheme there...) In my case I was decrypting when reading a file and then decrypting again when filling out a field. (desktop app)

当双解密一个值时,我看到了这个错误(密码就像你在这里说的那样)。一定要检查是否正在进行不止一次的解密。(我的错误是8的倍数,但我用的是另一种方法……)在我的例子中,我在读取文件时解密,然后在填写字段时再次解密。(桌面应用程序)

#3


-3  

This error indicates that you used choice combination requires 16 characters source text only. If you want to encrypt a password, you can truncate or pad the original password to 16-char for encryption, and trim after decryption. This way must limit real password not longer than 16-char, but you may apply longer used password to confuse those who should not know your password.

这个错误表明您使用的选择组合只需要16个字符的源文本。如果您想加密一个密码,您可以截断或填充原始密码到16字符的加密,并在解密后进行修整。这种方法必须限制真实密码不超过16字符,但是您可以使用更长的使用密码来迷惑那些不应该知道您密码的人。

#1


10  

Works on my machine. Does it help if you use `UNICODE_FORMAT' in every instance where you transform bytes to Strings and vice versa? This line could be a problem:

在我的机器上工作。如果在每个实例中都使用“UNICODE_FORMAT”将字节转换为字符串,反之亦然,这是否会有所帮助?这条线可能是个问题:

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

should be

应该是

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

Anyway, if you use "AES" as the algorithm and you use the JCE, the algorithm actually being used will be "AES/ECB/PKCS5Padding". Unless you are 100% sure about what you are doing, ECB shouldn't be used for anything. I'd recommend to always specify the algorithm explicitly in order to avoid such confusion. "AES/CBC/PKCS5Padding" would be a good choice. But watch out, with any reasonable algorithm you will also have to provide and manage an IV.

无论如何,如果你使用"AES"作为算法,你使用JCE,实际使用的算法将是"AES/ECB/PKCS5Padding。除非你百分之百确定自己在做什么,否则欧洲央行不应该被用来做任何事情。为了避免这种混淆,我建议始终明确地指定算法。“AES/CBC/PKCS5Padding(简称为AES)”是个不错的选择。但要小心,任何合理的算法你也必须提供和管理一个IV。

Using an ECB cipher is even less desirable in the context of encrypting passwords, which is what you seem to be doing with your encryption if I interpret your example correctly. You should use password-based encryption as specified in PKCS#5 for that purpose, in Java this is provided for you in SecretKeyFactory. Be sure to use "PBKDF2WithHmacSHA1" with a high enough iteration count (anything ranging from ~ 5-20 000, depends on your target machine) for using passwords to derive symmetric keys from them.

在加密密码的上下文中,使用欧洲央行密码甚至更不可取,如果我正确地解释了您的示例,您似乎正在使用您的加密。您应该在PKCS#5中为该目的使用基于密码的加密,在Java中,这是在SecretKeyFactory中为您提供的。确保使用“PBKDF2WithHmacSHA1”具有足够高的迭代计数(任何值在5- 20,000之间,取决于您的目标计算机)来使用密码从它们派生对称密钥。

The same technique can be used if it is actually password storage instead of password encryption what you are trying to achieve.

如果实际上是密码存储而不是密码加密,也可以使用相同的技术。

#2


-1  

I was seeing this error (with the password getting through just fine like you say here) when double-decrypting a value. Be sure to check to see if you are doing the decrypting more than once. (mine was multiple of 8 in the error, but I was using a different scheme there...) In my case I was decrypting when reading a file and then decrypting again when filling out a field. (desktop app)

当双解密一个值时,我看到了这个错误(密码就像你在这里说的那样)。一定要检查是否正在进行不止一次的解密。(我的错误是8的倍数,但我用的是另一种方法……)在我的例子中,我在读取文件时解密,然后在填写字段时再次解密。(桌面应用程序)

#3


-3  

This error indicates that you used choice combination requires 16 characters source text only. If you want to encrypt a password, you can truncate or pad the original password to 16-char for encryption, and trim after decryption. This way must limit real password not longer than 16-char, but you may apply longer used password to confuse those who should not know your password.

这个错误表明您使用的选择组合只需要16个字符的源文本。如果您想加密一个密码,您可以截断或填充原始密码到16字符的加密,并在解密后进行修整。这种方法必须限制真实密码不超过16字符,但是您可以使用更长的使用密码来迷惑那些不应该知道您密码的人。