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
- Confirm the encodingAesKey loaded matches the app that sent the callback message
- Log (length + prefix of) the received Encrypt string and verify it is valid Base64 with length % 4 == 0
- Check the e.printStackTrace() output for BadPaddingException — the classic symptom of a wrong key
- 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
- Maintain per-app key registries when multiple WeChat apps share a callback
- Verify msg_signature before decryption
- Read the full POST body to avoid truncated ciphertext
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)