Java AES解密BadPaddingException

Java AES解密BadPaddingException,java,encryption,cryptography,aes,badpaddingexception,Java,Encryption,Cryptography,Aes,Badpaddingexception,注:javanoob 好吧,我知道这个问题在这里已经被回答了几十次了,但是这些解决方案似乎并不适用于我理解它们的地方。(是的,我知道我不完全理解加密/解密、AES等。但这不是重点,我正在努力理解这一点) 我有一个实用程序api,我想传递一个字符串并返回一个加密字符串。然后我想传递加密的字符串,并返回一个解密的字符串。简单。对于我传入的许多字符串,它都可以正常工作,但在某些字符串上,我得到了异常javax.crypto.BadPaddingException:给定的最后一个块没有正确填充。 例如,

注:javanoob

好吧,我知道这个问题在这里已经被回答了几十次了,但是这些解决方案似乎并不适用于我理解它们的地方。(是的,我知道我不完全理解加密/解密、AES等。但这不是重点,我正在努力理解这一点)

我有一个实用程序api,我想传递一个字符串并返回一个加密字符串。然后我想传递加密的字符串,并返回一个解密的字符串。简单。对于我传入的许多字符串,它都可以正常工作,但在某些字符串上,我得到了异常
javax.crypto.BadPaddingException:给定的最后一个块没有正确填充。

例如,下面的加密/解密很好。
util/encrypt/?token=123456789012wha
=4TR0BCCQKQERK73ZR83AW==
util/decrypt/?token=4TR0CBCCKQERK73ZR83AW==
=123456789012wha

以下内容进行加密,但不解密:
util/encrypt/?token=123456789012什么
=NYaWmwnySoGNHyNmY9Jh+f3o2rqoli1acnsl5v4oce=
util/decrypt/?token=NYaWmwnySoGNHyNmY9Jh+f3o2rqoli1acnsl5v4oce=
=异常

以下是我的控制器中的代码:

private static final String ALGO = "AES";


@RequestMapping(value = "/util/encrypt/", method = RequestMethod.GET)
@ResponseBody
public String encrypt(HttpServletResponse httpResponse,
        @RequestParam(value = "token", required=true) String token) throws Exception 
{
    Key key = generateKey();
    Cipher c = Cipher.getInstance(ALGO);
    c.init(Cipher.ENCRYPT_MODE, key);
    byte[] encVal = c.doFinal(token.getBytes());
    String encryptedValue = Base64.encodeBase64String(encVal);
    return encryptedValue.trim();
}



@RequestMapping(value = "/util/decrypt/", method = RequestMethod.GET)
@ResponseBody
public String decrypt(HttpServletResponse httpResponse,
        @RequestParam(value = "token", required=true) String token) throws Exception 
{
    token = URLDecoder.decode(token, "UTF-8");
    Key key = generateKey();
    Cipher c = Cipher.getInstance(ALGO);
    c.init(Cipher.DECRYPT_MODE, key);
    byte[] decordedValue = Base64.decodeBase64(token);
    byte[] decValue = c.doFinal(decordedValue);
    String decryptedValue = new String(decValue);
    return decryptedValue.trim();
}



private Key generateKey() throws Exception 
{
    Key key = new SecretKeySpec(getAesKey().getBytes(), ALGO);
    return key;
}
我想一定是调用了
Cipher.getInstance()
,我尝试过使用
Cipher.getInstance(“AES/CBC/PKCS5Padding”)
,但解密时总是失败。我很想真正了解这里发生了什么,以及如何解决它

由于该类直接对字节流而不是字符流进行操作,因此它被硬编码为仅对与较低的127 ASCII图表(ISO-8859-1、Windows-1252、UTF-8等)兼容的字符编码进行编码/解码

从字节[]/string到字节[]/string的转换不会保留所有数据。密文的文本表示法实际上并不必要,所以为什么要转换为字符串?

使用该函数。javadoc说

使用base64算法的URL安全变体对二进制数据进行编码 但不会将输出分块。url安全变体发出-和_ 而不是+和/字符。注意:未添加任何填充


这应该可以解决问题。

我不确定我是否理解你的要求。我正在将cyphertext转换为字符串以返回到客户端。并非所有字节序列都是有效的UTF-8。在某个时刻,您的代码将引发异常。这里的另一个答案可以解决这个问题,也可以解决您看到的问题,这是由于URL中的“+”造成的。而且-我知道你认为你太聪明了,不在乎,但是-写你自己的密码是错误的。找一个你想要的图书馆。谢天谢地,我不太聪明,不在乎:)如果你知道一个图书馆,我会喜欢的。当我搜索时,我得到的是AES示例,而不是库。谢谢你的帮助。我想我想要像php的mcrypt库一样的东西。这就是我们的前端团队正在使用的。对不起,这有点刺耳。一般来说,如果你能开始工作,那就是最好的解决方案。它尽力防止您出错。请注意,
“AES”
默认为
“AES/ECB/PKCS5Padding”
(对于SUN提供程序),不适合加密字符串。还请注意,在通过网络连接发送密文时,通常需要身份验证标签(例如,为了抵御oracle攻击)。工作代码不等于加密安全代码。@earthling我当然会在加密后执行HMAC签名(使用不同的密钥),并在解密前验证MAC值。更高级别的加密框架,如Keyczar(我个人不使用),几乎肯定比推出自己的解决方案更安全——特别是如果你只是在互联网上学习示例,而不是了解一般的加密技术。@earthling是的,CBC肯定比ECB好。但正如owlstead指出的,在这种情况下,验证密文的真实性也相当重要。您可以使用HMAC,或者(最好)使用类似的东西来实现,它结合了加密和身份验证。请注意,您还必须使用CBC+HMAC-SHA256传输128位的IV和256位的身份验证标记,而您通常使用96位的IV和96位的身份验证标记与GCM一起使用。@ntoskrnl…并且您可以使用相同的密钥进行GCM。但是GCM并不像HMAC那样普及。@ntoskrnl是的,我是它们的大力拥护者,但有时你仍然需要检查它们是否适用于所需的运行时。(即将发布的)TLS和XML加密规范中提到了它们,这给了我们一些希望:)