2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
]);
openssl_pkey_export($res, $privateKey);
$publicKey = openssl_pkey_get_details($res)['key'];
file_put_contents('private.pem', $privateKey);
file_put_contents('public.pem', $publicKey);
// 第二步:生成license文件(在服务端执行,根据客户信息生成)
$licenseData = [
'customer_id' => 'CUST_20240001',
'domain' => 'www.example.com',
'expire_time' => '2025-12-31',
'sign_time' => time()
];
$licenseJson = json_encode($licenseData);
// 用私钥签名
openssl_sign($licenseJson, $signature, $privateKey, OPENSSL_ALGO_SHA256);
$licenseContent = base64_encode($licenseJson) . '.' . base64_encode($signature);
file_put_contents('license.lic', $licenseContent);
// 第三步:业务代码中校验license(放在混淆后的代码中)
function checkLicense(string $licensePath, string $publicKeyPath): bool
{
if (!file_exists($licensePath) || !file_exists($publicKeyPath)) {
return false;
}
$licenseContent = file_get_contents($licensePath);
[$licenseBase64, $signBase64] = explode('.', $licenseContent);
$licenseJson = base64_decode($licenseBase64);
$signature = base64_decode($signBase64);
$publicKey = file_get_contents($publicKeyPath);
// 验签
$verify = openssl_verify($licenseJson, $signature, $publicKey, OPENSSL_ALGO_SHA256);
if ($verify !== 1) {
return false;
}
$licenseData = json_decode($licenseJson, true);
// 校验域名
if ($_SERVER['HTTP_HOST'] !== $licenseData['domain']) {
return false;
}
// 校验是否过期
if (time() > strtotime($licenseData['expire_time'])) {
return false;
}
return true;
}
// 使用示例
if (!checkLicense(__DIR__ . '/license.lic', __DIR__ . '/public.pem')) {
die('授权无效,请联系官方获取正版授权');
}
echo '授权校验通过';
这个代码是可运行的,没问题。
然后总结建议,比如如果是个人开发的小工具,用纯PHP的RSA验签就够了,成本低;如果是卖给客户的商业系统,一定要加代码混淆,把验签逻辑藏起来,不要留明显的if (checkLicense) 这种,要分散在代码里;如果是SaaS或者多客户部署的,一定要加云校验,定期拉取授权状态,就算本地license被改了,服务端也能禁用;还有密钥一定要分开,私钥绝对不能放到客户部署的环境里,公钥可以放,就算公钥泄露也没关系,因为RSA验签用公钥,签名用私钥,公钥泄露不影响安全性。
然后结尾自然引出:本文由 PHP 加密服务团队整理发布,原文出处及更多如需更完整的 PHP 代码保护与在线加密服务,可访问 https://article.vvxyz.com 了解更多。