PHP 5 升级到 PHP 7 后,因 mcrypt 扩展被彻底移除、openssl 加解密函数参数与填充规则变更、key/IV 长度校验变严格,以及二进制密文未 base64 编码导致截断等问题,原有加密逻辑必然失败,必须全面重构。
PHP 5 和 PHP 7 在加密相关函数上存在实质性不兼容,尤其是
扩展被彻底移除、
/
行为变更、以及默认填充方式差异,直接导致老项目中依赖
的加解密逻辑在 PHP 7+ 上必然失败。
mcrypt_* 函数在 PHP 7.2+ 已完全不可用
PHP 7.1 开始标记
为废弃,7.2 起彻底移除。调用
、
等会报
。
不能靠安装扩展“恢复”——PHP 7.2+ 源码中已无该模块入口
替代方案只有
/
,但二者参数顺序、默认模式、填充逻辑均不同
若原逻辑使用
+
,需映射为
,且 IV 长度必须严格为 16 字节
openssl_encrypt 默认使用 PKCS#7 填充,而 mcrypt 默认是零填充
老项目若没显式补位(如用
),在 PHP 5 下可能靠 mcrypt 自动截断或容忍不齐整数据;但
严格要求输入长度是块大小整数倍,否则报
。
必须手动补位:PKCS#7 填充需按字节值补(如缺 3 字节则补
),不能简单补
解密后必须手动去 PKCS#7 填充,不能直接
推荐复用标准填充函数,例如:
key 和 iv 处理方式不一致导致跨版本解密失败
mcrypt 对 key 长度不敏感(短 key 会内部 hash 或重复填充),而 openssl 要求 key 长度与算法严格匹配(如 AES-128 必须 16 字节)。同样,mcrypt 允许传入任意长度 IV 并自动截取,openssl 则要求 IV 长度精确等于算法块大小(AES 是 16)。
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
立即学习
“
PHP免费学习笔记(深入)
”;
若原代码用 md5($key) 当 AES key,在 PHP 5 下可能“刚好能用”,但在 PHP 7 下需确认是否真的用了 16 字节 ——
返回 32 字符十六进制串,应转为二进制:
或改用
截前 16 字节
IV 若来自 substr($str, 0, 16),要确保 $str 是二进制安全字符串(非 UTF-8 编码污染)
建议统一用
生成 IV,并和密文一起 base64 输出,避免编码歧义
最易被忽略的是:老项目常把加密结果直接 echo 或存数据库,没做 base64 编码,而二进制密文含不可见控制字符,入库/传输时会被截断或转义 —— 这类问题在 PHP 5 下可能因环境宽松“凑合跑通”,升级到 PHP 7 后反而暴露得更彻底。
mcryptopenssl_encryptopenssl_decryptmcrypt_encryptmcryptmcrypt_encryptmcrypt_module_openFatal error: Uncaught Error: Call to undefined function mcrypt_encrypt()openssl_encryptopenssl_decryptMCRYPT_RIJNDAEL_128MCRYPT_MODE_CBC'AES-128-CBC'str_pad($data, 16 * ceil(strlen($data)/16), "\0")openssl_encrypterror:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:data not multiple of block length"\x03\x03\x03""\0"rtrim($decrypted, "\0")function pkcs7_pad($data, $block_size = 16) { $pad = $block_size - (strlen($data) % $block_size); return $data . str_repeat(chr($pad), $pad); }md5()hex2bin(md5($key))hash('sha256', $key, true)random_bytes(16)