iflytek/astron-agent · error · AesException

-40007

-40007

Error message

AES decryption failed

What it means

The decrypt method wraps any failure while Base64-decoding the ciphertext or running AES decryption into AesException(-40007, 'AES decryption failed'). This means the incoming encrypted message could not be decrypted with the configured key — usually a key mismatch or corrupted/invalid ciphertext.

Solutions

  1. Confirm the encodingAesKey loaded matches the app that sent the callback message
  2. Log (length + prefix of) the received Encrypt string and verify it is valid Base64 with length % 4 == 0
  3. Check the e.printStackTrace() output for BadPaddingException — the classic symptom of a wrong key
  4. If serving multiple apps, route decryption by appid and select the matching key

Example fix

// before
WXBizMsgCrypt crypt = new WXBizMsgCrypt(token, sharedKey, appId); // decrypts every app with one key
// after
String key = appKeyRegistry.get(appId); // per-app key
WXBizMsgCrypt crypt = new WXBizMsgCrypt(token, key, appId);
Defensive patterns

Strategy: try-catch

Validate before calling

String enc = doc.getElementsByTagName("Encrypt").item(0).getTextContent().trim(); if (enc.length() % 4 != 0 || !enc.matches("^[A-Za-z0-9+/=]+$")) { throw new BadRequestException("malformed Encrypt field"); }

Try / catch

try { String xml = crypt.decrypt(encrypt, signature, timestamp, nonce); } catch (AesException e) { if (e.getCode() == -40007 || e.getCode() == -40008) { log.warn("decrypt failed for appId {} — likely key mismatch", appId); throw new BadCallbackException(e); } throw e; }

Prevention

When it happens

Trigger: Decrypting a message from a different WeChat app whose AES key differs from the configured one, ciphertext containing whitespace/newlines or missing characters from bad message extraction, or the raw POST body parsed with the wrong XML field.

Common situations: Multiple WeChat apps behind one callback URL with the wrong app's key loaded, config hot-reload picking up a stale key, proxies/serialization mangling the Base64 in the Encrypt field, or the message tampered/replayed.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/3669aee7325ee7ee. Report an issue: GitHub.

Appendix: source

Thrown at console/backend/hub/src/main/java/com/iflytek/astron/console/hub/util/wechat/WXBizMsgCrypt.java:164

     * @throws AesException AES decryption failed
     */
    String decrypt(String text) throws AesException {
        byte[] original;
        try {
            // Set decryption mode to AES CBC mode
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec key_spec = new SecretKeySpec(aesKey, "AES");
            IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
            cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);

            // Use BASE64 to decode ciphertext
            byte[] encrypted = Base64.decodeBase64(text);

            // Decrypt
            original = cipher.doFinal(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
            throw new AesException(AesException.DecryptAESError);
        }

        String xmlContent, from_appid;
        try {
            // Remove padding
            byte[] bytes = PKCS7Encoder.decode(original);

            // Separate 16-bit random string, network byte order, and appId
            byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);

            int xmlLength = recoverNetworkBytesOrder(networkOrder);

            xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET);
            from_appid = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length),
                    CHARSET);
        } catch (Exception e) {
            e.printStackTrace();
            throw new AesException(AesException.IllegalBuffer);

View on GitHub (pinned to 5e758547a8)