thinkphp 使用 rsa 需手动封装或引入第三方类;常见问题包括 openssl 未启用、公钥格式错误(必须为 pem 标准格式)、明文超长(2048 位限 245 字节)、验签时原始字符串不一致及编码不匹配。

ThinkPHP 本身不内置 RSA 加密类,所有 openssl_* 相关操作都得自己封装或引入第三方类;直接调用 Rsa::encrypt() 却没输出,大概率是密钥加载失败、参数传错,或者根本没启用 OpenSSL 扩展。
openssl 扩展没启用,openssl_pkey_get_public 就会返回 false
这是最常被忽略的前置条件。不检查就写加密逻辑,后面全白忙。
- 运行
phpinfo();,搜索openssl,确认“enabled”为 yes - 若未启用,打开
php.ini,取消注释extension=openssl,重启 Web 服务(Apache/Nginx + PHP-FPM) - 命令行下执行
php -m | grep openssl,也得看到输出 - 别信“本地能跑线上就不能”——很多云主机/容器环境默认不开启
公钥格式不对,openssl_pkey_get_public 静默失败
PHP 的 openssl_pkey_get_public() 对 PEM 格式极其敏感,错一个字符、少一行换行、多一个空格都会返回 false。
- 公钥必须以
-----BEGIN PUBLIC KEY-----开头,-----END PUBLIC KEY-----结尾(不是-----BEGIN RSA PUBLIC KEY-----) - 中间 Base64 内容每行不能超过 64 字符,可用
chunk_split($key, 64, "\n")修复 - 从文件读取时,别用
trim()或str_replace(["\r\n", "\n"], "", $key)——这会破坏格式 - Linux 下推荐用
openssl rsa -in private.pem -pubout -out pub.pem生成;Windows 下用 Git Bash 或 WSL 执行同命令
openssl_public_encrypt 明文超长,返回 false 且无提示
2048 位 RSA 密钥 + PKCS#1 填充,最多只能加密 245 字节原始数据。JSON 字符串稍一复杂就超限。
- 用
strlen($data)检查明文字节数,不是mb_strlen()或数组长度 - 超长时不要硬拆分——RSA 不支持分块加密;应改用「RSA + AES 混合加密」:用 RSA 加密一次性的 AES 密钥,再用该 AES 密钥加密业务数据
- 别在加密前做
urlencode()或json_encode()多套一层——这些都会额外增加字节数 - 加密后务必
base64_encode(),解密前必须base64_decode(),漏一步就解不出
ThinkPHP 中验签失败,90% 是原始字符串没还原一致
签名和验签必须用完全相同的原始字符串。但 ThinkPHP 的 $request->param() 已自动 urldecode,而签名时拼的是 a=x%20y&b=z 这种原始形式。
- 验签前必须重新构造:剔除
sign、timestamp等非业务字段 →ksort()排序 → 对每个 value 调用rawurlencode()(不是urlencode())→ 拼成a=b&c=d形式 - 别用
$request->get()或$request->post()单独取参,它们可能丢失嵌套结构或自动转义 - 验签函数第三个参数必须是
OPENSSL_ALGO_SHA256常量,写成字符串'sha256'会失败 - 密钥 resource 缓存比每次都
file_get_contents()读文件更高效,尤其高并发场景
真正麻烦的从来不是“怎么调函数”,而是密钥格式、原始串一致性、编码层级这些细节——它们不会报错,只会让 openssl_verify() 返回 false,然后你花两小时查文档,最后发现公钥开头少了个 -。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











