在 PHP 中实现使用私钥对数据进行签名、客户端使用公钥验证签名、客户端使用公钥加密数据、服务器使用私钥解密数据的功能,可以利用 OpenSSL 扩展。
1. 安装 OpenSSL 扩展
确保你的 PHP 环境中已经安装了 OpenSSL 扩展。大多数 PHP 安装默认都会包含这个扩展。你可以通过以下命令检查是否已安装:
php -m | grep openssl
如果没有安装,可以使用包管理器安装:
-
Debian/Ubuntu:
sudo apt-get install php-openssl
-
CentOS/RHEL:
sudo yum install php-openssl
2. 生成密钥对
首先,生成一个 RSA 密钥对(私钥和公钥)。
# 生成私钥
openssl genpkey -algorithm RSA -out private_key.pem -aes256
# 从私钥中提取公钥
openssl rsa -pubout -in private_key.pem -out public_key.pem
3. PHP 代码示例
3.1 服务器端:生成签名和解密数据
<?php
// 读取私钥
$privateKey = file_get_contents('private_key.pem');
$privateKeyId = openssl_pkey_get_private($privateKey, 'your_private_key_password'); // 如果私钥有密码
// 读取公钥
$publicKey = file_get_contents('public_key.pem');
$publicKeyId = openssl_pkey_get_public($publicKey);
// 要签名的数据
$data = 'This is a secret message.';
// 生成签名
$signature = '';
openssl_sign($data, $signature, $privateKeyId, OPENSSL_ALGO_SHA256);
// 将签名编码为 Base64
$signatureBase64 = base64_encode($signature);
// 输出签名
echo "Signature: " . $signatureBase64 . PHP_EOL;
// 模拟客户端加密数据
$encryptedData = '';
openssl_public_encrypt($data, $encryptedData, $publicKeyId);
// 将加密后的数据编码为 Base64
$encryptedDataBase64 = base64_encode($encryptedData);
// 输出加密后的数据
echo "Encrypted Data: " . $encryptedDataBase64 . PHP_EOL;
// 释放资源
openssl_free_key($privateKeyId);
openssl_free_key($publicKeyId);
?>
3.2 客户端:验证签名和加密数据
<?php
// 读取公钥
$publicKey = file_get_contents('public_key.pem');
$publicKeyId = openssl_pkey_get_public($publicKey);
// 读取私钥
$privateKey = file_get_contents('private_key.pem');
$privateKeyId = openssl_pkey_get_private($privateKey, 'your_private_key_password'); // 如果私钥有密码
// 要验证的数据
$data = 'This is a secret message.';
// 从服务器获取的签名
$signatureBase64 = '...'; // 替换为从服务器获取的签名
$signature = base64_decode($signatureBase64);
// 验证签名
$verified = openssl_verify($data, $signature, $publicKeyId, OPENSSL_ALGO_SHA256);
if ($verified === 1) {
echo "Signature is valid." . PHP_EOL;
} elseif ($verified === 0) {
echo "Signature is invalid." . PHP_EOL;
} else {
echo "Error verifying signature." . PHP_EOL;
}
// 从服务器获取的加密数据
$encryptedDataBase64 = '...'; // 替换为从服务器获取的加密数据
$encryptedData = base64_decode($encryptedDataBase64);
// 解密数据
$decryptedData = '';
openssl_private_decrypt($encryptedData, $decryptedData, $privateKeyId);
// 输出解密后的数据
echo "Decrypted Data: " . $decryptedData . PHP_EOL;
// 释放资源
openssl_free_key($publicKeyId);
openssl_free_key($privateKeyId);
?>
4. 详细解释
生成签名
-
openssl_sign
:使用私钥对数据进行签名。- 参数:
$data
:要签名的数据。$signature
:签名结果。$privateKeyId
:私钥资源。OPENSSL_ALGO_SHA256
:签名算法(SHA-256)。
- 参数:
-
base64_encode
:将签名编码为 Base64,便于传输。
验证签名
openssl_verify
:使用公钥验证签名。- 参数:
$data
:要验证的数据。$signature
:签名结果。$publicKeyId
:公钥资源。OPENSSL_ALGO_SHA256
:签名算法(SHA-256)。
- 返回值:
1
:签名有效。0
:签名无效。-1
:验证过程中发生错误。
- 参数:
加密数据
-
openssl_public_encrypt
:使用公钥对数据进行加密。- 参数:
$data
:要加密的数据。$encryptedData
:加密后的数据。$publicKeyId
:公钥资源。
- 参数:
-
base64_encode
:将加密后的数据编码为 Base64,便于传输。
解密数据
openssl_private_decrypt
:使用私钥对数据进行解密。- 参数:
$encryptedData
:加密后的数据。$decryptedData
:解密后的数据。$privateKeyId
:私钥资源。
- 参数:
总结
通过上述示例,你可以在 PHP 中实现使用私钥对数据进行签名、客户端使用公钥验证签名、客户端使用公钥加密数据、服务器使用私钥解密数据的功能。这些操作基于 OpenSSL 扩展,提供了强大的加密和签名功能。