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

  1. Re-fetch a fresh sessionKey via the login (code2Session/jscode2session) flow immediately before decrypting — keys invalidate on each new login.
  2. Verify encryptedData and iv are raw Base64 strings and have not been URL/JSON-escaped twice.
  3. Inspect the wrapped cause (e.getCause()) to distinguish BadPaddingException / InvalidKeyException / decoding errors.
  4. 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

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


AI-assisted analysis of binarywang/WxJava@1c43293a3c (2026-08-14). Data as JSON: /api/errors/af26aee0a212c605. Report an issue: GitHub.