yiisoft/yii2 · error · InvalidConfigException

Encryption requires the OpenSSL PHP extension

Error message

Encryption requires the OpenSSL PHP extension

What it means

yii\base\Security::encrypt() — the shared engine behind encryptByKey() and encryptByPassword() — refuses to run without the OpenSSL PHP extension because the AES-CBC pipeline needs openssl_encrypt/openssl_decrypt plus authenticated encryption. The InvalidConfigException fires before any key derivation or cipher validation, so this is purely an environment problem, not a data or key problem.

Source

Thrown at framework/base/Security.php:202

    /**
     * Encrypts data.
     *
     * @param string $data data to be encrypted
     * @param bool $passwordBased set true to use password-based key derivation
     * @param string $secret the encryption password or key
     * @param string|null $info context/application specific information, e.g. a user ID
     * See [RFC 5869 Section 3.2](https://tools.ietf.org/html/rfc5869#section-3.2) for more details.
     *
     * @return string the encrypted data as byte string
     * @throws InvalidConfigException on OpenSSL not loaded
     * @throws Exception on OpenSSL error
     * @see decrypt()
     */
    protected function encrypt($data, $passwordBased, $secret, $info)
    {
        if (!extension_loaded('openssl')) {
            throw new InvalidConfigException('Encryption requires the OpenSSL PHP extension');
        }
        if (!isset($this->allowedCiphers[$this->cipher][0], $this->allowedCiphers[$this->cipher][1])) {
            throw new InvalidConfigException($this->cipher . ' is not an allowed cipher');
        }

        list($blockSize, $keySize) = $this->allowedCiphers[$this->cipher];

        $keySalt = $this->generateRandomKey($keySize);
        if ($passwordBased) {
            $key = $this->pbkdf2($this->kdfHash, $secret, $keySalt, $this->derivationIterations, $keySize);
        } else {
            $key = $this->hkdf($this->kdfHash, $secret, $keySalt, $info, $keySize);
        }

        $iv = $this->generateRandomKey($blockSize);

        $encrypted = openssl_encrypt($data, $this->cipher, $key, OPENSSL_RAW_DATA, $iv);
        if ($encrypted === false) {

View on GitHub (pinned to 66f00d18a2)

Solutions

  1. Install/enable the extension in the failing runtime: docker-php-ext-install openssl in Docker builds, apk add php83-openssl on Alpine, apt install php-openssl on Debian, or uncomment extension=openssl in php.ini
  2. Confirm with php -m | grep openssl inside the exact runtime that throws (CLI vs FPM vs worker container can differ)
  3. Declare the requirement in composer.json ('require': {'ext-openssl': '*'}) so installs fail early on bad environments
  4. Where encryption is unavailable, degrade explicitly (skip and queue the operation) instead of swallowing the exception

Example fix

# before: Dockerfile
FROM php:8.3-cli
# ext-openssl missing → encryptByKey() throws InvalidConfigException

# after
FROM php:8.3-cli
RUN docker-php-ext-install openssl
Defensive patterns

Strategy: validation

Validate before calling

if (!extension_loaded('openssl')) {
    throw new \RuntimeException('Encryption features require ext-openssl');
}
$ciphertext = Yii::$app->security->encryptByKey($data, $key);

Try / catch

try {
    $ct = Yii::$app->security->encryptByKey($data, $key);
} catch (\yii\base\InvalidConfigException $e) {
    // environment misconfiguration — surface it, never retry
    \Yii::error($e->getMessage(), 'security');
}

Prevention

When it happens

Trigger: Calling encryptByKey()/encryptByPassword() on a runtime where ext-openssl is absent or disabled: official php:8.x-cli images built without it, Alpine splits (php83-openssl not installed), extension commented out in php.ini, or minimal custom builds.

Common situations: Works on the dev machine (bundled OpenSSL) but fails in slim Docker/Alpine images; hosting tiers without the extension; upgraded base images dropping it; CI matrices missing the package.

Related errors


AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17). Data as JSON: /api/errors/e27c5985b6ddeb27. Report an issue: GitHub.