{"record":{"id":"60d53713879bf441","repo":"yiisoft/yii2","slug":"openssl-failure-on-encryption-error","errorCode":null,"errorMessage":"OpenSSL failure on encryption: {error}","messagePattern":"OpenSSL failure on encryption: (.+?)","errorType":"exception","errorClass":"yii\\base\\Exception","httpStatus":null,"severity":"error","filePath":"framework/base/Security.php","lineNumber":221,"sourceCode":"        }\n        if (!isset($this->allowedCiphers[$this->cipher][0], $this->allowedCiphers[$this->cipher][1])) {\n            throw new InvalidConfigException($this->cipher . ' is not an allowed cipher');\n        }\n\n        list($blockSize, $keySize) = $this->allowedCiphers[$this->cipher];\n\n        $keySalt = $this->generateRandomKey($keySize);\n        if ($passwordBased) {\n            $key = $this->pbkdf2($this->kdfHash, $secret, $keySalt, $this->derivationIterations, $keySize);\n        } else {\n            $key = $this->hkdf($this->kdfHash, $secret, $keySalt, $info, $keySize);\n        }\n\n        $iv = $this->generateRandomKey($blockSize);\n\n        $encrypted = openssl_encrypt($data, $this->cipher, $key, OPENSSL_RAW_DATA, $iv);\n        if ($encrypted === false) {\n            throw new \\yii\\base\\Exception('OpenSSL failure on encryption: ' . openssl_error_string());\n        }\n\n        $authKey = $this->hkdf($this->kdfHash, $key, null, $this->authKeyInfo, $keySize);\n        $hashed = $this->hashData($iv . $encrypted, $authKey);\n\n        /*\n         * Output: [keySalt][MAC][IV][ciphertext]\n         * - keySalt is KEY_SIZE bytes long\n         * - MAC: message authentication code, length same as the output of MAC_HASH\n         * - IV: initialization vector, length $blockSize\n         */\n        return $keySalt . $hashed;\n    }\n\n    /**\n     * Decrypts data.\n     *\n     * @param string $data encrypted data to be decrypted.","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/yiisoft/yii2/blob/66f00d18a29b520f85e8e8f1e32d1e7e7b556cac/framework/base/Security.php#L203-L239","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n$sec = new Security(['cipher' => 'CAMELLIA-256-CBC']); // not compiled into this OpenSSL\n$ct = $sec->encryptByKey($data, $key);\n\n// after\n$sec = Yii::$app->security; // default AES-128-CBC\nif (!in_array(strtolower($sec->cipher), array_map('strtolower', openssl_get_cipher_methods()), true)) {\n    throw new \\RuntimeException('Cipher unavailable on this host: ' . $sec->cipher);\n}\n$ct = $sec->encryptByKey($data, $key);","handlingStrategy":"validation","validationCode":"$cipher = Yii::$app->security->cipher;\nif (!\\in_array(\\strtolower($cipher), \\array_map('strtolower', openssl_get_cipher_methods()), true)) {\n    throw new \\RuntimeException('Configured cipher is unavailable on this host: ' . $cipher);\n}\n$ct = Yii::$app->security->encryptByKey($data, $key);","typeGuard":null,"tryCatchPattern":"try {\n    $ct = Yii::$app->security->encryptByKey($data, $key);\n} catch (\\yii\\base\\Exception $e) {\n    // fail closed — never store plaintext instead\n    \\Yii::error('Encryption failed: ' . $e->getMessage(), 'security');\n    throw new \\RuntimeException('Cannot secure data on this system', 0, $e);\n}","preventionTips":["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."],"tags":["security","encryption","openssl","environment","yii2"],"backgroundTag":"openssl-encryption-failed","analyzedSha":"66f00d18a29b520f85e8e8f1e32d1e7e7b556cac","analyzedAt":"2026-08-17T05:17:23.470Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}