yiisoft/yii2 · error · yii\base\Exception

OpenSSL failure on encryption: {error}

Error message

OpenSSL failure on encryption: {error}

What it means

Security::encryptByKey()/encryptByPassword() derive correctly-sized key material and then call openssl_encrypt(); a false return is wrapped in yii\base\Exception together with openssl_error_string(). Because Yii derives the key length from the cipher, the realistic causes are the configured Security::$cipher not being available to the loaded OpenSSL build, or a broken OpenSSL extension/config rather than bad input.

Source

Thrown at framework/base/Security.php:221

        }
        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) {
            throw new \yii\base\Exception('OpenSSL failure on encryption: ' . openssl_error_string());
        }

        $authKey = $this->hkdf($this->kdfHash, $key, null, $this->authKeyInfo, $keySize);
        $hashed = $this->hashData($iv . $encrypted, $authKey);

        /*
         * Output: [keySalt][MAC][IV][ciphertext]
         * - keySalt is KEY_SIZE bytes long
         * - MAC: message authentication code, length same as the output of MAC_HASH
         * - IV: initialization vector, length $blockSize
         */
        return $keySalt . $hashed;
    }

    /**
     * Decrypts data.
     *
     * @param string $data encrypted data to be decrypted.

View on GitHub (pinned to 66f00d18a2)

Solutions

  1. Verify cipher availability at boot: in_array(strtolower($cipher), array_map('strtolower', openssl_get_cipher_methods()), true) — fall back to Yii's default 'AES-128-CBC' if missing.
  2. Confirm the openssl extension is loaded (php -m) and openssl.cnf exists where OpenSSL expects it.
  3. Keep cipher/KDF settings identical across every environment that shares encrypted data — changing them later makes existing ciphertext undecryptable.
  4. Wrap encrypt calls in try/catch and fail closed (block the operation); never fall back to storing plaintext.

Example fix

// before
$sec = new Security(['cipher' => 'CAMELLIA-256-CBC']); // not compiled into this OpenSSL
$ct = $sec->encryptByKey($data, $key);

// after
$sec = Yii::$app->security; // default AES-128-CBC
if (!in_array(strtolower($sec->cipher), array_map('strtolower', openssl_get_cipher_methods()), true)) {
    throw new \RuntimeException('Cipher unavailable on this host: ' . $sec->cipher);
}
$ct = $sec->encryptByKey($data, $key);
Defensive patterns

Strategy: validation

Validate before calling

$cipher = Yii::$app->security->cipher;
if (!\in_array(\strtolower($cipher), \array_map('strtolower', openssl_get_cipher_methods()), true)) {
    throw new \RuntimeException('Configured cipher is unavailable on this host: ' . $cipher);
}
$ct = Yii::$app->security->encryptByKey($data, $key);

Try / catch

try {
    $ct = Yii::$app->security->encryptByKey($data, $key);
} catch (\yii\base\Exception $e) {
    // fail closed — never store plaintext instead
    \Yii::error('Encryption failed: ' . $e->getMessage(), 'security');
    throw new \RuntimeException('Cannot secure data on this system', 0, $e);
}

Prevention

When it happens

Trigger: A Security component configured with a cipher the environment's OpenSSL does not register (legacy or renamed methods); moving an app from a distro PHP to a bundled/Alpine PHP with a different OpenSSL; encrypting cookies/session data so the throw surfaces exactly at login; a misconfigured openssl.cnf making the extension error out at call time.

Common situations: Environment drift between dev and prod OpenSSL builds; configs carried over from mcrypt-era setups after a Yii upgrade; partially installed PHP openssl extension; Docker images swapping base images without re-checking cipher availability.

Related errors


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