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
- 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.
- Confirm the openssl extension is loaded (php -m) and openssl.cnf exists where OpenSSL expects it.
- Keep cipher/KDF settings identical across every environment that shares encrypted data — changing them later makes existing ciphertext undecryptable.
- 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
- Add a bootstrap check that the configured cipher exists in openssl_get_cipher_methods().
- Pin the security component's cipher/kdf settings in version control and keep them identical everywhere.
- Verify the openssl extension in deployment smoke tests (php -m, openssl_error_string() empty).
- Alert on any encryption exception — it usually means environment drift.
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
- Encryption requires the OpenSSL PHP extension
- {cipher} is not an allowed cipher
- OpenSSL failure on decryption: {error}
- Invalid parameters to hash_hkdf()
- Invalid parameters to hash_pbkdf2()
AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17).
Data as JSON: /api/errors/60d53713879bf441.
Report an issue: GitHub.