binarywang/WxJava · error · IllegalStateException

AES CBC decrypt failed

Error message

AES CBC decrypt failed

What it means

Thrown by `decryptAesCbcFromBase64` when AES/CBC decryption fails (GeneralSecurityException wrapped as IllegalStateException). Causes: the ciphertext is not valid base64, was tampered/truncated, padding is wrong, or the key does not match the one used for encryption (IV is derived from the key's first 16 bytes).

Source

Thrown at weixin-java-aispeech/src/main/java/me/chanjar/weixin/aispeech/util/WxAispeechSignUtil.java:55

      byte[] keyBytes = decodeAesKey(aesKey);
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
      cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, "AES"), new IvParameterSpec(Arrays.copyOf(keyBytes, 16)));
      byte[] encrypted = cipher.doFinal(defaultString(plainText).getBytes(StandardCharsets.UTF_8));
      return Base64.encodeBase64String(encrypted);
    } catch (GeneralSecurityException e) {
      throw new IllegalStateException("AES CBC encrypt failed", e);
    }
  }

  public static String decryptAesCbcFromBase64(String cipherTextBase64, String aesKey) {
    try {
      byte[] keyBytes = decodeAesKey(aesKey);
      Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
      cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBytes, "AES"), new IvParameterSpec(Arrays.copyOf(keyBytes, 16)));
      byte[] encrypted = Base64.decodeBase64(defaultString(cipherTextBase64));
      return new String(cipher.doFinal(encrypted), StandardCharsets.UTF_8);
    } catch (GeneralSecurityException e) {
      throw new IllegalStateException("AES CBC decrypt failed", e);
    }
  }

  private static byte[] decodeAesKey(String aesKey) {
    return Base64.decodeBase64(defaultString(aesKey) + "=");
  }

  private static String defaultString(String value) {
    return value == null ? "" : value;
  }

  private static String bytesToHex(byte[] bytes) {
    StringBuilder builder = new StringBuilder(bytes.length * 2);
    for (byte b : bytes) {
      builder.append(String.format("%02x", b));
    }
    return builder.toString();
  }

View on GitHub (pinned to 1c43293a3c)

Solutions

  1. Confirm the aesKey is the exact one used to encrypt this payload.
  2. Ensure the ciphertext base64 is intact (no truncation, no embedded whitespace).
  3. Check the wrapped cause: BadPaddingException usually means wrong key or tampered data.
  4. If payloads are URL-transmitted, verify base64 URL-safety/encoding alignment.

Example fix

// before
String p = WxAispeechSignUtil.decryptAesCbcFromBase64(cipherText, wrongKey);  // throws
// after
String p = WxAispeechSignUtil.decryptAesCbcFromBase64(cipherText.trim(), correctKey);
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate inputs before decrypting
if (StringUtils.isBlank(cipherTextBase64) || StringUtils.isBlank(aesKey)) {
    throw new IllegalArgumentException("ciphertext and aesKey are required");
}
byte[] keyBytes = java.util.Base64.getDecoder().decode(aesKey.trim() + "=");
if (keyBytes.length < 16) {
    throw new IllegalArgumentException("AES key too short for IV derivation");
}

Try / catch

try {
    String plain = WxAispeechSignUtil.decryptAesCbcFromBase64(cipherTextBase64, aesKey);
} catch (IllegalStateException e) {
    // BadPaddingException => wrong key or tampered/truncated ciphertext
    log.error("AES decrypt failed; check key match and ciphertext integrity", e.getCause());
    throw e;
}

Prevention

When it happens

Trigger: Passing a wrong aesKey for the given ciphertext; corrupted/truncated base64 ciphertext; ciphertext from a different key session; bad padding from an incomplete payload.

Common situations: Key mismatch after rotation; copy-paste truncation of the ciphertext; transport layer corrupting the base64 string.

Related errors


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