{"record":{"id":"3669aee7325ee7ee","repo":"iflytek/astron-agent","slug":"40007-aes-decryption-failed","errorCode":"-40007","errorMessage":"AES decryption failed","messagePattern":"AES decryption failed","errorType":"error_code","errorClass":"AesException","httpStatus":null,"severity":"error","filePath":"console/backend/hub/src/main/java/com/iflytek/astron/console/hub/util/wechat/WXBizMsgCrypt.java","lineNumber":164,"sourceCode":"     * @throws AesException AES decryption failed\n     */\n    String decrypt(String text) throws AesException {\n        byte[] original;\n        try {\n            // Set decryption mode to AES CBC mode\n            Cipher cipher = Cipher.getInstance(\"AES/CBC/NoPadding\");\n            SecretKeySpec key_spec = new SecretKeySpec(aesKey, \"AES\");\n            IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));\n            cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);\n\n            // Use BASE64 to decode ciphertext\n            byte[] encrypted = Base64.decodeBase64(text);\n\n            // Decrypt\n            original = cipher.doFinal(encrypted);\n        } catch (Exception e) {\n            e.printStackTrace();\n            throw new AesException(AesException.DecryptAESError);\n        }\n\n        String xmlContent, from_appid;\n        try {\n            // Remove padding\n            byte[] bytes = PKCS7Encoder.decode(original);\n\n            // Separate 16-bit random string, network byte order, and appId\n            byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);\n\n            int xmlLength = recoverNetworkBytesOrder(networkOrder);\n\n            xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET);\n            from_appid = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length),\n                    CHARSET);\n        } catch (Exception e) {\n            e.printStackTrace();\n            throw new AesException(AesException.IllegalBuffer);","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/hub/src/main/java/com/iflytek/astron/console/hub/util/wechat/WXBizMsgCrypt.java#L146-L182","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nWXBizMsgCrypt crypt = new WXBizMsgCrypt(token, sharedKey, appId); // decrypts every app with one key\n// after\nString key = appKeyRegistry.get(appId); // per-app key\nWXBizMsgCrypt crypt = new WXBizMsgCrypt(token, key, appId);","handlingStrategy":"try-catch","validationCode":"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\"); }","typeGuard":null,"tryCatchPattern":"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; }","preventionTips":["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"],"tags":["java","wechat","aes","decryption"],"backgroundTag":"aes-decrypt-failed","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}