tp5.1起think_encrypt/think_decrypt被移除,改用crypt::encrypt()/decrypt(),基于openssl aes-128-cbc,密钥须16字节,不兼容tp5.0自定义异或加密。

Thinkphp 5.1 的 think_encrypt 和 think_decrypt 已被移除
TP5.1 开始,框架不再内置对称加密助手函数。如果你在旧项目里直接调用 think_encrypt,运行会报 Call to undefined function think_encrypt()。这不是配置问题,是函数确实没了——官方把加解密逻辑下沉到 thinkhelperStr 和独立的 thinkfacadeCrypt(需手动引入扩展)。
实际迁移时,推荐改用 Crypt::encrypt() / Crypt::decrypt(),但要注意它默认使用 OpenSSL + AES-128-CBC,密钥长度必须为 16 字节,且不兼容 TP5.0 的 think_encrypt 输出(后者用的是自定义异或+base64,无标准算法标识)。
thinkphp 6.x 默认使用 think-crypt 扩展,但需显式安装和配置
TP6 不再把加密能力打包进核心,而是拆成可选组件 topthink/think-crypt。没装这个包,Crypt::encrypt() 会提示类不存在;装了但没发布配置,会因找不到 config/crypt.php 报错。
正确做法是:
立即学习“PHP免费学习笔记(深入)”;
- 执行
composer require topthink/think-crypt - 运行
php think vendor:publish拉取默认配置 - 检查
config/crypt.php中的key是否为 16/24/32 字节(对应 AES-128/192/256),不能直接填明文字符串,建议用bin2hex(random_bytes(16))生成 - 避免把
cipher改成des或rc4—— 这些在新版 OpenSSL 中已被废弃,PHP 8.1+ 会直接报Unsupported cipher
TP5.0 的 think_encrypt 无法与 TP6 的 Crypt::encrypt 互解
两者算法完全不同:TP5.0 是纯 PHP 实现的简单混淆(str_replace + 异或 + base64),没有 IV、无标准填充,密钥当作字符串直接参与运算;TP6 用的是标准 OpenSSL 封装,带随机 IV、PKCS7 填充、HMAC 签名校验。
这意味着:
- TP5.0 加密的字符串,在 TP6 下调用
Crypt::decrypt()必然失败,错误通常是openssl_decrypt(): Decryption failed - 反向也不行:TP6 加密结果 base64 解码后是 48 字节以上(含 IV + 密文 + HMAC),而 TP5.0 期望的是固定结构的短字符串
- 如需兼容老数据,必须保留 TP5.0 的原始加密逻辑单独写解密函数,不能试图“适配”新 Crypt 类
自定义加密函数时,别忽略 openssl_random_pseudo_bytes 的返回值校验
很多手写 AES 加密的示例直接用 openssl_random_pseudo_bytes(16) 生成 IV,但该函数第二个参数是引用布尔值,表示是否强随机。如果系统熵池不足(如某些 docker 容器或低配 VPS),可能返回弱随机数甚至 false,导致后续 openssl_encrypt 报 IV Length must be the same as block size。
稳妥写法是:
- 用
random_bytes(16)替代(PHP 7.0+,强制强随机) - 若需兼容 PHP openssl_random_pseudo_bytes 返回值,并 fallback 到更保守的方案(如
uniqid(mt_rand(), true)+ hash) - 永远把 IV 和密文一起存储或传输,TP6 的
Crypt自动处理了这点,但自己封装时容易漏掉 IV 导致解密失败
跨版本迁移加密逻辑时,最常被忽略的是密钥编码方式和 IV 传递机制——不是“换个函数就行”,而是要确认整个加解密上下文是否一致。哪怕只差一个字节的密钥或少传 16 字节 IV,结果都是完全不可逆的乱码。