binarywang/WxJava · error · IllegalStateException

AES CBC encrypt failed

Error message

AES CBC encrypt failed

What it means

Thrown by `encryptAesCbcToBase64` when AES/CBC/PKCS5Padding encryption fails (GeneralSecurityException wrapped as IllegalStateException). The key is derived by base64-decoding `aesKey + "="`, so the usual cause is an invalid/incorrectly-padded key, a wrong key length, or an unusable provider.

Source

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

      + defaultString(requestBody);
    try {
      Mac mac = Mac.getInstance("HmacSHA256");
      mac.init(new SecretKeySpec(defaultString(secretKey).getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
      return bytesToHex(mac.doFinal(payload.getBytes(StandardCharsets.UTF_8)));
    } catch (GeneralSecurityException e) {
      throw new IllegalStateException("HmacSHA256 signature failed", e);
    }
  }

  public static String encryptAesCbcToBase64(String plainText, String aesKey) {
    try {
      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) + "=");
  }

View on GitHub (pinned to 1c43293a3c)

Solutions

  1. Verify the aesKey decodes cleanly from base64 to 16/24/32 bytes.
  2. Trim whitespace/newlines from the key before passing it.
  3. Confirm the key matches what the server expects for this session.
  4. Inspect the wrapped GeneralSecurityException cause (InvalidKeyException vs IllegalBlockSizeException).

Example fix

// before
String c = WxAispeechSignUtil.encryptAesCbcToBase64(plain, "not-valid-base64!!");  // throws
// after
String key = aesKey.trim();  // ensure clean, valid base64 decoding to 16/24/32 bytes
String c = WxAispeechSignUtil.encryptAesCbcToBase64(plain, key);
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the AES key before encrypting
byte[] keyBytes = java.util.Base64.getDecoder().decode(aesKey.trim() + "=");
if (keyBytes.length != 16 && keyBytes.length != 24 && keyBytes.length != 32) {
    throw new IllegalArgumentException("Invalid AES key length: " + keyBytes.length);
}

Try / catch

try {
    String cipher = WxAispeechSignUtil.encryptAesCbcToBase64(plain, aesKey);
} catch (IllegalStateException e) {
    // cause is InvalidKeyException / IllegalBlockSizeException etc.
    log.error("AES encrypt failed, likely bad key", e.getCause());
    throw e;
}

Prevention

When it happens

Trigger: Passing an aesKey that is not valid base64, has the wrong bit length after decoding (AES needs 16/24/32 bytes), or a tampered key string. The IV is the first 16 bytes of the key, so a short key also breaks IV init.

Common situations: Wrong key copied from console (truncated/whitespace); key encoded differently than expected; secret rotated but client not updated.

Related errors


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