跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

PHP5与PHP7加密差异_老项目升级兼容加密函数注意【介绍】

PHP 5 升级到 PHP 7 后,因 mcrypt 扩展被彻底移除、openssl 加解密函数参数与填充规则变更、key/IV 长度校验变严格,以及二进制密文未 base64 编码导致截断等问题,原有加密逻辑必然失败,必须全面重构。 PHP 5 和 PHP 7 在加密相关函数上存在实质性不兼容,尤其是
mcrypt
扩展被彻底移除、
openssl_encrypt
/
openssl_decrypt
行为变更、以及默认填充方式差异,直接导致老项目中依赖
mcrypt_encrypt
的加解密逻辑在 PHP 7+ 上必然失败。 mcrypt_* 函数在 PHP 7.2+ 已完全不可用 PHP 7.1 开始标记
mcrypt
为废弃,7.2 起彻底移除。调用
mcrypt_encrypt
mcrypt_module_open
等会报
Fatal error: Uncaught Error: Call to undefined function mcrypt_encrypt()
。 不能靠安装扩展“恢复”——PHP 7.2+ 源码中已无该模块入口 替代方案只有
openssl_encrypt
/
openssl_decrypt
,但二者参数顺序、默认模式、填充逻辑均不同 若原逻辑使用
MCRYPT_RIJNDAEL_128
+
MCRYPT_MODE_CBC
,需映射为
'AES-128-CBC'
,且 IV 长度必须严格为 16 字节 openssl_encrypt 默认使用 PKCS#7 填充,而 mcrypt 默认是零填充 老项目若没显式补位(如用
str_pad($data, 16 * ceil(strlen($data)/16), "\0")
),在 PHP 5 下可能靠 mcrypt 自动截断或容忍不齐整数据;但
openssl_encrypt
严格要求输入长度是块大小整数倍,否则报
error:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:data not multiple of block length
。 必须手动补位:PKCS#7 填充需按字节值补(如缺 3 字节则补
"\x03\x03\x03"
),不能简单补
"\0"
解密后必须手动去 PKCS#7 填充,不能直接
rtrim($decrypted, "\0")
推荐复用标准填充函数,例如:
function pkcs7_pad($data, $block_size = 16) { $pad = $block_size - (strlen($data) % $block_size); return $data . str_repeat(chr($pad), $pad); }
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 字节 ——
md5()
返回 32 字符十六进制串,应转为二进制:
hex2bin(md5($key))
或改用
hash('sha256', $key, true)
截前 16 字节 IV 若来自 substr($str, 0, 16),要确保 $str 是二进制安全字符串(非 UTF-8 编码污染) 建议统一用
random_bytes(16)
生成 IV,并和密文一起 base64 输出,避免编码歧义 最易被忽略的是:老项目常把加密结果直接 echo 或存数据库,没做 base64 编码,而二进制密文含不可见控制字符,入库/传输时会被截断或转义 —— 这类问题在 PHP 5 下可能因环境宽松“凑合跑通”,升级到 PHP 7 后反而暴露得更彻底。

相关文章