
在 PHP 中,生成签名和验证签名是确保数据完整性和安全性的重要手段。签名通常用于 API 请求、数据传输等场景,以防止数据被篡改。以下是生成签名和验证签名的详细实现方法及示例代码。
1. 生成签名
生成签名的基本步骤如下:
将需要签名的数据按一定规则排序(如按参数名升序)。
将排序后的数据拼接成字符串。
使用密钥对拼接后的字符串进行加密(如 HMAC-SHA256)。
将加密结果转换为签名。
示例代码
<?phpfunction generateSignature($data, $secretKey) {
// 1. 按参数名升序排序
ksort($data);
// 2. 拼接字符串
$stringToSign = '';
foreach ($data as $key => $value) {
$stringToSign .= $key . '=' . $value . '&';
}
$stringToSign = rtrim($stringToSign, '&');
// 3. 使用 HMAC-SHA256 加密
$signature = hash_hmac('sha256', $stringToSign, $secretKey);
return $signature;}// 示例数据$data = [
'name' => 'John Doe',
'email' => 'john@example.com',
'timestamp' => time(),];$secretKey = 'your_secret_key';// 生成签名$signature = generateSignature($data, $secretKey);echo "生成的签名: $signature\n";?>2. 验证签名
验证签名的基本步骤如下:
从请求中获取签名和数据。
按照生成签名的规则重新生成签名。
比较生成的签名与请求中的签名是否一致。
示例代码
<?phpfunction verifySignature($data, $secretKey, $receivedSignature) {
// 1. 按参数名升序排序
ksort($data);
// 2. 拼接字符串
$stringToSign = '';
foreach ($data as $key => $value) {
$stringToSign .= $key . '=' . $value . '&';
}
$stringToSign = rtrim($stringToSign, '&');
// 3. 使用 HMAC-SHA256 加密
$generatedSignature = hash_hmac('sha256', $stringToSign, $secretKey);
// 4. 比较签名
return hash_equals($generatedSignature, $receivedSignature);}// 示例数据$data = [
'name' => 'John Doe',
'email' => 'john@example.com',
'timestamp' => time(),];$secretKey = 'your_secret_key';$receivedSignature = '生成的签名'; // 替换为实际接收到的签名// 验证签名if (verifySignature($data, $secretKey, $receivedSignature)) {
echo "签名验证成功!";} else {
echo "签名验证失败!";}?>3. 注意事项
密钥管理:
密钥(
$secretKey)必须保密,不能泄露。建议将密钥存储在环境变量或配置文件中。
数据排序:
生成签名时,必须按照相同的规则排序数据,否则签名验证会失败。
时间戳:
在数据中加入时间戳(如
timestamp),可以防止重放攻击。验证签名时,检查时间戳是否在有效范围内。
哈希算法:
推荐使用
HMAC-SHA256,安全性较高。避免使用 MD5 或 SHA1 等不安全的哈希算法。
签名比较:
使用
hash_equals()比较签名,避免时序攻击。
4. 完整示例
以下是一个完整的示例,包括生成签名、发送请求、接收请求并验证签名。
客户端代码(生成签名并发送请求)
<?phpfunction generateSignature($data, $secretKey) {
ksort($data);
$stringToSign = '';
foreach ($data as $key => $value) {
$stringToSign .= $key . '=' . $value . '&';
}
$stringToSign = rtrim($stringToSign, '&');
return hash_hmac('sha256', $stringToSign, $secretKey);}$data = [
'name' => 'John Doe',
'email' => 'john@example.com',
'timestamp' => time(),];$secretKey = 'your_secret_key';$signature = generateSignature($data, $secretKey);// 将签名添加到数据中$data['signature'] = $signature;// 发送请求$url = 'https://example.com/api';$ch = curl_init($url);curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);$response = curl_exec($ch);curl_close($ch);echo "服务器响应: $response\n";?>服务器端代码(验证签名)
<?phpfunction verifySignature($data, $secretKey, $receivedSignature) {
ksort($data);
$stringToSign = '';
foreach ($data as $key => $value) {
if ($key !== 'signature') { // 排除签名字段
$stringToSign .= $key . '=' . $value . '&';
}
}
$stringToSign = rtrim($stringToSign, '&');
$generatedSignature = hash_hmac('sha256', $stringToSign, $secretKey);
return hash_equals($generatedSignature, $receivedSignature);}// 获取 POST 数据$data = $_POST;$receivedSignature = $data['signature'];$secretKey = 'your_secret_key';// 验证签名if (verifySignature($data, $secretKey, $receivedSignature)) {
echo "签名验证成功!";} else {
echo "签名验证失败!";}?>5. 总结
| 步骤 | 说明 |
|---|---|
| 生成签名 | 按规则排序数据,拼接字符串,使用 HMAC 加密 |
| 验证签名 | 重新生成签名并与接收到的签名比较 |
| 密钥管理 | 确保密钥保密 |
| 时间戳 | 防止重放攻击 |
| 哈希算法 | 推荐使用 HMAC-SHA256 |
| 签名比较 | 使用 hash_equals() 避免时序攻击 |
通过以上方法,可以确保数据在传输过程中的完整性和安全性。
希望以上内容对你有所帮助!如果还有其他问题,请随时提问。 各类知识收集 拥有多年CMS企业建站经验,对 iCMS, LeCMS, ClassCMS, Fastadmin, PbootCMS, PHPCMS, 易优CMS, YzmCMS, 讯睿CMS, 极致CMS, Wordpress, HkCMS, YznCMS, WellCMS, ThinkCMF, 等各类cms的相互转化,程序开发,网站制作,bug修复,程序杀毒,插件定制都可以提供最佳解决方案。


