w7corp/easywechat · error · InvalidArgumentException

Decrypt AES CBC error.

Error message

Decrypt AES CBC error.

What it means

Support\AesCbc::decrypt() returns false from openssl_decrypt (bad key, bad IV, or corrupted ciphertext) and throws InvalidArgumentException with openssl_error_string() or the fallback 'Decrypt AES CBC error.'. In EasyWeChat this helper backs MiniApp\Decryptor::decrypt(), which rewraps the failure as DecryptException('The given payload is invalid: ...') — the classic symptom of a wrong or expired WeChat session_key when decrypting wx.getUserProfile / phone-number payloads.

Source

Thrown at src/Kernel/Support/AesCbc.php:44

        return base64_encode($ciphertext);
    }

    /**
     * @throws InvalidArgumentException
     */
    public static function decrypt(string $ciphertext, string $key, ?string $iv = null): string
    {
        $plaintext = openssl_decrypt(
            base64_decode($ciphertext),
            'aes-128-cbc',
            $key,
            OPENSSL_RAW_DATA,
            (string) $iv
        );

        if ($plaintext === false) {
            throw new InvalidArgumentException(openssl_error_string() ?: 'Decrypt AES CBC error.');
        }

        return $plaintext;
    }
}

View on GitHub (pinned to f0cf0a8b83)

Solutions

  1. Re-run the login flow (code2session) to obtain a fresh session_key, store it keyed by openid, then retry the decrypt
  2. Confirm iv and encryptedData come from the same client invocation (e.g. the same getPhoneNumber/getUserProfile result) as the session_key
  3. Check the wrapped message: DecryptException text includes the underlying reason from openssl_error_string()

Example fix

// before
$payload = Decryptor::decrypt($cachedSessionKey, $iv, $encryptedData); // DecryptException

// after
try {
    $payload = Decryptor::decrypt($cachedSessionKey, $iv, $encryptedData);
} catch (DecryptException $e) {
    // session_key likely rotated: force re-login on the mini program side
    $session = $api->get('/sns/jscode2session', [...]);
    $cachedSessionKey = $session['session_key'];
    $payload = Decryptor::decrypt($cachedSessionKey, $iv, $encryptedData);
}
Defensive patterns

Strategy: try-catch

Try / catch

use EasyWeChat\Kernel\Exceptions\DecryptException;

try {
    $payload = \EasyWeChat\MiniApp\Decryptor::decrypt($sessionKey, $iv, $encryptedData);
} catch (DecryptException $e) {
    // session_key rotated or mismatched: re-run code2session and retry once
    $newSessionKey = $this->refreshSessionKey($openid); // your code2session wrapper
    if ($newSessionKey !== null && $newSessionKey !== $sessionKey) {
        $payload = \EasyWeChat\MiniApp\Decryptor::decrypt($newSessionKey, $iv, $encryptedData);
    } else {
        throw $e; // genuinely corrupt payload
    }
}

Prevention

When it happens

Trigger: Calling MiniApp Decryptor::decrypt($sessionKey, $iv, $encryptedData) where session_key is stale (user re-logged-in elsewhere, rotating the key) or does not match the code2session result used to fetch it; or the iv/encryptedData came from a different client call than the session_key.

Common situations: Cached session_key reused after the user logged in again (keys rotate per login), dev/prod appid mismatch, env or openid-keyed cache returning another user's key, passing base64 values undecoded.

Related errors


AI-assisted analysis of w7corp/easywechat@f0cf0a8b83 (2026-08-21). Data as JSON: /api/errors/cd66ca1532f03750. Report an issue: GitHub.