PHP OpenSSL PKI加密技术详解:私钥公钥互操作与签名验证

洛溪
洛溪
发布时间:2026-10-14| 6人浏览过
原创

本文详解PHP中使用OpenSSL扩展进行RSA非对称加密的方法。涵盖私钥加密公钥解密、公钥加密私钥解密两种模式,以及openssl_sign与openssl_verify的签名生成与验证流程。同时说明密钥文件获取的注意事项及内存释放步骤,确保数据安全传输。

核心机制与准备工作

PKI(公钥基础设施)在PHP中的实现主要依赖 openssl 扩展。其核心逻辑分为两种场景:

  1. 数据加密:用于保密传输。通常使用接收方的公钥加密,只有持有对应私钥的一方才能解密。
  2. 数字签名:用于身份认证和数据完整性校验。发送方使用自己的私钥对数据进行签名,接收方使用发送方的公钥验证签名,确认数据来源和未被篡改。

在使用前,请确保 PHP 配置文件 php.ini 中已启用 extension=openssl 或 extension=php_openssl.dll(Windows环境)。

第一种方式:私钥加密,公钥解密

这种模式通常不常用于常规数据加密,因为其安全性依赖于私钥的保密性。但在某些特定协议或数字信封场景中可能会遇到。此模式使用私钥加密后,任何人都可以用对应的公钥解密,因此它不具备机密性,但具备来源不可否认性。

第1步:加载密钥文件

首先需要读取本地的私钥文件和公钥文件,并获取密钥资源ID。

$priv_key_id = openssl_get_privatekey(file_get_contents('private-rsa.pem'));
$pub_key_id = openssl_get_publickey(file_get_contents('public-rsa.cer'));

第2步:私钥加密过程

使用 openssl_private_encrypt() 函数,将原始数据通过私钥进行加密。注意,RSA加密的数据长度受密钥长度限制(例如2048位密钥最多加密245字节),长数据需分块或使用混合加密。

$data = '敏感信息';
$crypted = '';
// 私钥加密
openssl_private_encrypt($data, $crypted, $priv_key_id); 
echo bin2hex($crypted); // 输出十六进制便于查看

第3步:公钥解密验证

使用 openssl_public_decrypt() 函数,用对应的公钥对密文进行解密,恢复原始数据。

$decrypted = '';
// 公钥解密
openssl_public_decrypt($crypted, $decrypted, $pub_key_id);
echo $decrypted; // 应输出:敏感信息

第二种方式:公钥加密,私钥解密(推荐)

这是标准的非对称加密数据传输方式。发送方使用接收方的公钥加密数据,确保只有持有私钥的接收方可以阅读内容。

第1步:公钥加密

使用 openssl_public_encrypt() 函数,通过公钥加密数据。

$data = '需要保密的数据';
$crypted = '';
// 公钥加密
openssl_public_encrypt($data, $crypted, $pub_key_id); 
echo bin2hex($crypted);

第2步:私钥解密

使用 openssl_private_decrypt() 函数,通过私钥解密数据。

$decrypted = '';
// 私钥解密
openssl_private_decrypt($crypted, $decrypted, $priv_key_id);
echo $decrypted; // 应输出:需要保密的数据

数字签名生成与验证

在实际业务中(如支付接口、API调用),除了数据加密,更需要保证数据的完整性和发送者身份。openssl_sign() 和 openssl_verify() 是专门用于处理签名的函数。

第1步:生成签名

发送方使用自己的私钥对原始数据进行哈希和签名运算。推荐使用 OPENSSL_ALGO_SHA256 或 OPENSSL_ALGO_SHA1 等算法。

$data = '订单号:12345,金额:100';
$signature = '';
// 使用SHA256算法进行签名
openssl_sign($data, $signature, $priv_key_id, OPENSSL_ALGO_SHA256); 
echo bin2hex($signature);

第2步:验证签名

接收方使用发送方的公钥对数据和签名进行验证,确认数据是否被篡改以及是否确实由私钥持有者发出。

$result = openssl_verify($data, $signature, $pub_key_id, OPENSSL_ALGO_SHA256);
if ($result === 1) {
    echo "签名有效";
} else if ($result === 0) {
    echo "签名无效";
} else {
    echo "验证出错";
}

密钥管理与注意事项

密钥匹配问题

在实际开发中(如对接第三方支付平台快钱、微信支付等),经常会出现官方提供的公钥和私钥文件来自不同生成场景的情况。例如,官方可能提供给你一对用于验证签名的密钥,而另一对用于加密通信。务必确保你使用的公钥和私钥是严格对应的,否则加解密或签名验证将失败。如果遇到“找不到对应文件”的情况,请联系服务商获取完整的密钥对,或通过标准算法从DER/PEM格式中提取或转换。

手动生成密钥对

如果需要本地测试,可以使用 OpenSSL 命令行工具生成密钥对:

# 生成2048位私钥
openssl genrsa -out private-rsa.pem 2048

# 从私钥提取公钥
openssl rsa -in private-rsa.pem -pubout -out public-rsa.cer

资源清理

为了节省内存,在处理完密钥后,应显式释放密钥资源:

openssl_free_key($priv_key_id);
openssl_free_key($pub_key_id);

总结

PHP 中的 OpenSSL 模块提供了完善的 RSA 非对称加密能力。在日常开发中,建议优先使用“公钥加密、私钥解密”保障数据机密性,使用“私钥签名、公钥验签”保障数据完整性和抗否认性。使用时需注意密钥对的匹配性以及数据长度的限制。以上就是PHP OpenSSL PKI加密技术的详细内容,更多关于PHP安全开发及OpenSSL应用技巧的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。