binarywang/WxJava · error · RuntimeException
AES解密失败!
Error message
AES解密失败!
What it means
WxChCryptUtils.decrypt performs AES/CBC/NoPadding decryption of WeChat-encrypted data (e.g. channel/miniapp user encryptedData) using a sessionKey and iv, both Base64-decoded. Any failure in key derivation, IV init, ciphering, or Base64 decoding is caught and rethrown as a generic RuntimeException. The original cause is attached as the exception's cause.
Source
Thrown at weixin-java-channel/src/main/java/me/chanjar/weixin/channel/util/WxChCryptUtils.java:47
/**
* AES解密
*
* @param sessionKey session_key
* @param encryptedData 消息密文
* @param ivStr iv字符串
*/
public static String decrypt(String sessionKey, String encryptedData, String ivStr) {
try {
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
params.init(new IvParameterSpec(Base64.decodeBase64(ivStr)));
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(Base64.decodeBase64(sessionKey), "AES"), params);
return new String(PKCS7Encoder.decode(cipher.doFinal(Base64.decodeBase64(encryptedData))), UTF_8);
} catch (Exception e) {
throw new RuntimeException("AES解密失败!", e);
}
}
}
View on GitHub (pinned to 1c43293a3c)
Solutions
- Re-fetch a fresh sessionKey via the login (code2Session/jscode2session) flow immediately before decrypting — keys invalidate on each new login.
- Verify encryptedData and iv are raw Base64 strings and have not been URL/JSON-escaped twice.
- Inspect the wrapped cause (e.getCause()) to distinguish BadPaddingException / InvalidKeyException / decoding errors.
- Ensure the encryptedData and iv come from the same WeChat callback/login response (they are paired).
Example fix
// before — stale key reused String plain = WxChCryptUtils.decrypt(oldSessionKey, encryptedData, iv); // after — fresh key per login WxMiniacppSessionResult s = service.jsCode2Session(jsCode); String plain = WxChCryptUtils.decrypt(s.getSessionKey(), encryptedData, iv);
Defensive patterns
Strategy: validation
Validate before calling
if (sessionKey == null || ivStr == null || encryptedData == null
|| !Base64.isBase64(sessionKey) || !Base64.isBase64(ivStr)) {
throw new IllegalArgumentException("sessionKey/iv/encryptedData missing or not Base64");
}
// then decrypt Try / catch
try {
String plain = WxChCryptUtils.decrypt(sessionKey, encryptedData, iv);
} catch (RuntimeException e) {
// e.getCause() reveals BadPaddingException / InvalidKeyException etc.
log.warn("AES decrypt failed, sessionKey may be stale", e.getCause());
// re-fetch sessionKey and retry once, or fail the flow
} Prevention
- Fetch a fresh sessionKey via code2Session immediately before each decrypt — keys invalidate on new logins.
- Validate that encryptedData and iv are raw Base64 and paired from the same login response.
- Log e.getCause() to distinguish wrong-key vs corrupted-data failures.
When it happens
Trigger: Calling decrypt with a wrong/stale sessionKey, a mismatched iv, a malformed (non-Base64 or truncated) encryptedData, or data encrypted with a different algorithm/padding scheme.
Common situations: sessionKey expired because a new code2Session login occurred (keys are single-use per login); iv or encryptedData copied with truncation or encoding corruption; Unicode/percent-encoding mangled the payload in transit.
Related errors
- AES CBC encrypt failed
- AES CBC decrypt failed
- 请确保微信视频号配置 appId 的唯一性
- 请确保微信视频号配置 appId 的唯一性
- HmacSHA256 signature failed
AI-assisted analysis of binarywang/WxJava@1c43293a3c (2026-08-14).
Data as JSON: /api/errors/af26aee0a212c605.
Report an issue: GitHub.