注意:Java NOOB。
好吧,我知道这个问题在这里已经回答了几十次,但这些解决方案似乎不起作用/不直接适用于我理解的地方。(是的,我知道我不完全理解加密/解密、AES等,但这不是重点,我正在努力理解这一点)
我有一个实用程序api,我想在其中传递一个字符串并返回一个加密的字符串。然后我想传递加密的字符串,并返回一个解密的字符串。易于理解的它适用于我传入的许多字符串,但在某些字符串上,我得到了异常javax.crypto.BadPaddingException: Given final block not properly padded.
例如,下面的加密/解密很好util/encrypt/?token=123456789012wha
=4TR0CbCcQKqeRK73zr83aw=util/decrypt/?token=4TR0CbCcQKqeRK73zr83aw==
=12346789012ha
以下加密但不解密:util/encrypt/?token=123456789012what
=NYaWmwnySoGNHyNmY9Jh+f3O2RQOLI1Acnsl5V4OCE=util/decrypt/?token=NYaWmwnySoGNHyNmY9Jh+f3O2rqoLI1IAcnsl5V4OCE=
=异常
这是我的控制器中的代码:
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")
,但在解密时总是失败。我很想真正了解这里发生了什么以及如何修复它。
使用函数encodeBase64URLSafeString。javadoc说
使用base64算法的URL安全变体对二进制数据进行编码但是不对输出进行组块。url安全变体发出-和_而不是+和/字符。注意:不添加任何填充。
这应该能解决问题。
由于此类直接对字节流而非字符流进行操作,因此它被硬编码为仅对与下127 ASCII图表(ISO-8859-1、Windows-1252、UTF-8等)兼容的字符编码进行编码/解码。
您对byte[]/string的转换不会保留所有数据。密文的文本表示其实并不必要,那么为什么要转换为字符串呢?