编程 PHP中RSA加密和签名操作的性能瓶颈

2025-03-21 13:54:28 +0800 CST views 218

事情起因是这样的

21-Mar-2025 05:31:59]  [pool www] pid 494782
script_filename = /www/wwwroot/killme/admin/testsubmit.php
[0x00007f52dc016320] bcpowmod() /www/wwwroot/killme/plugins/pay2c2/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php:103
[0x00007f52dc016290] modPow() /www/wwwroot/killme/plugins/pay2c2/vendor/brick/math/src/BigInteger.php:663
[0x00007f52dc016200] modPow() /www/wwwroot/killme/plugins/pay2c2/vendor/web-token/jwt-framework/src/Component/Core/Util/BigInteger.php:152
[0x00007f52dc016170] modPow() /www/wwwroot/killme/plugins/pay2c2/vendor/web-token/jwt-framework/src/Component/Core/Util/RSAKey.php:220
[0x00007f52dc016050] exponentiate() /www/wwwroot/killme/plugins/pay2c2/vendor/web-token/jwt-framework/src/SignatureAlgorithm/RSA/Util/RSA.php:69
[0x00007f52dc015f90] signWithPSS() /www/wwwroot/killme/plugins/pay2c2/vendor/web-token/jwt-framework/src/SignatureAlgorithm/RSA/Util/RSA.php:47
[0x00007f52dc015ed0] sign() /www/wwwroot/killme/plugins/pay2c2/vendor/web-token/jwt-framework/src/SignatureAlgorithm/RSA/RSAPSS.php:49
[0x00007f52dc015e40] sign() /www/wwwroot/killme/plugins/pay2c2/vendor/web-token/jwt-framework/src/Component/Signature/JWSBuilder.php:168
[0x00007f52dc015d20] build() /www/wwwroot/killme/plugins/pay2c2/inc/SecurityData.php:211
[0x00007f52dc015c60] EncryptPayload() /www/wwwroot/killme/plugins/pay2c2/pay2c2_plugin.php:261
[0x00007f52dc015a60] submit() /www/wwwroot/killme/includes/lib/Plugin.php:101
[0x00007f52dc015760] loadClass() /www/wwwroot/killme/includes/lib/Plugin.php:86
[0x00007f52dc0153f0] loadForSubmit() /www/wwwroot/killme/admin/testsubmit.php:22

[21-Mar-2025 05:32:59]  [pool www] pid 494786
script_filename = /www/wwwroot/killme/admin/testsubmit.php
[0x00007f52dc016320] bcpowmod() /www/wwwroot/killme/plugins/pay2c2/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php:103
[0x00007f52dc016290] modPow() /www/wwwroot/killme/plugins/pay2c2/vendor/brick/math/src/BigInteger.php:663
[0x00007f52dc016200] modPow() /www/wwwroot/killme/plugins/pay2c2/vendor/web-token/jwt-framework/src/Component/Core/Util/BigInteger.php:152
[0x00007f52dc016170] modPow() /www/wwwroot/killme/plugins/pay2c2/vendor/web-token/jwt-framework/src/Component/Core/Util/RSAKey.php:219
[0x00007f52dc016050] exponentiate() /www/wwwroot/killme/plugins/pay2c2/vendor/web-token/jwt-framework/src/SignatureAlgorithm/RSA/Util/RSA.php:69
[0x00007f52dc015f90] signWithPSS() /www/wwwroot/killme/plugins/pay2c2/vendor/web-token/jwt-framework/src/SignatureAlgorithm/RSA/Util/RSA.php:47
[0x00007f52dc015ed0] sign() /www/wwwroot/killme/plugins/pay2c2/vendor/web-token/jwt-framework/src/SignatureAlgorithm/RSA/RSAPSS.php:49
[0x00007f52dc015e40] sign() /www/wwwroot/killme/plugins/pay2c2/vendor/web-token/jwt-framework/src/Component/Signature/JWSBuilder.php:168
[0x00007f52dc015d20] build() /www/wwwroot/killme/plugins/pay2c2/inc/SecurityData.php:211
[0x00007f52dc015c60] EncryptPayload() /www/wwwroot/killme/plugins/pay2c2/pay2c2_plugin.php:261
[0x00007f52dc015a60] submit() /www/wwwroot/killme/includes/lib/Plugin.php:101
[0x00007f52dc015760] loadClass() /www/wwwroot/killme/includes/lib/Plugin.php:86
[0x00007f52dc0153f0] loadForSubmit() /www/wwwroot/killme/admin/testsubmit.php:22

php 慢日志监控 发现需要42秒

提供的日志来看,问题似乎集中在 bcpowmod() 函数的调用上,该函数用于大数运算,尤其是在 RSA 加密和签名过程中。bcpowmod() 是一个计算密集型操作,尤其是在处理大数时,可能会导致性能瓶颈。

可能的原因
大数运算复杂度高:RSA 加密和签名操作涉及大数运算,尤其是模幂运算(bcpowmod),这在处理大密钥时可能会非常耗时。

密钥长度过大:如果使用的 RSA 密钥长度非常大(例如 4096 位),计算时间会显著增加。

硬件资源不足:服务器的 CPU 性能不足,或者 PHP 配置不当,可能导致运算速度变慢。

代码优化不足:如果代码中没有对 RSA 运算进行优化,或者频繁调用这些操作,可能会导致性能问题。

解决方案
检查密钥长度:

确保使用的 RSA 密钥长度适中。通常 2048 位的密钥在安全性和性能之间提供了良好的平衡。如果密钥长度过大(如 4096 位),考虑使用更短的密钥。

检查 /www/wwwroot/killmepay.com/plugins/pay2c2/inc/SecurityData.php 或相关配置文件,确认密钥长度。

优化代码:

检查 /www/wwwroot/killmepay.com/plugins/pay2c2/pay2c2_plugin.php 和 /www/wwwroot/killmepay.com/admin/testsubmit.php 中的代码,确保没有不必要的 RSA 运算。

如果可能,缓存签名结果,避免重复计算。

升级硬件或优化 PHP 配置:

如果服务器 CPU 性能不足,考虑升级硬件。

检查 PHP 配置(php.ini),确保 bcmath 扩展已启用,并且 PHP 的内存限制(memory_limit)和最大执行时间(max_execution_time)设置合理。

使用更高效的算法:

如果 RSA 运算确实是瓶颈,考虑使用更高效的加密算法,例如 ECC(椭圆曲线加密),它在相同安全级别下比 RSA 更快。

性能分析:

使用性能分析工具(如 Xdebug 或 Blackfire)来分析代码的执行时间,找出具体的性能瓶颈。

需要提供的文件
为了进一步分析问题,可以提供以下文件:

/www/wwwroot/killme/plugins/pay2c2/inc/SecurityData.php

/www/wwwroot/killme/plugins/pay2c2/pay2c2_plugin.php

/www/wwwroot/killme/admin/testsubmit.php

/www/wwwroot/killme/plugins/pay2c2/vendor/web-token/jwt-framework/src/Component/Core/Util/RSAKey.php

/www/wwwroot/killm/plugins/pay2c2/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php

这些文件将帮助我们更深入地分析代码逻辑和性能瓶颈。

总结
你可以从检查密钥长度、优化代码、升级硬件或调整 PHP 配置入手。如果问题依然存在,建议使用性能分析工具进一步定位问题。
从你提供的 `SecurityData.php` 文件来看,代码主要涉及 JWT(JSON Web Token)的签名、加密和解密操作,使用了 `web-token/jwt-framework` 库。性能瓶颈可能集中在以下几个方面:

---

### **1. RSA 密钥长度**
从代码中可以看到,RSA 密钥的长度可能较大(例如 2048 位或 4096 位)。RSA 的加密、解密和签名操作是计算密集型的,尤其是模幂运算(`bcpowmod`),密钥长度越大,计算时间越长。

#### **解决方案**
- **检查密钥长度**:确保使用的 RSA 密钥长度适中。通常 2048 位的密钥在安全性和性能之间提供了良好的平衡。如果密钥长度过大(如 4096 位),考虑使用更短的密钥。
- **切换到 ECC(椭圆曲线加密)**:ECC 在相同安全级别下比 RSA 更快,且密钥长度更短。例如,256 位的 ECC 密钥提供的安全性相当于 3072 位的 RSA 密钥。

---

### **2. 频繁的加密和签名操作**
在 `EncryptPayload` 方法中,代码对每个请求都进行了 JWS(签名)和 JWE(加密)操作。这些操作涉及大量的数学计算,尤其是在高并发场景下,可能会导致性能瓶颈。

#### **解决方案**
- **缓存签名结果**:如果某些数据是静态的或可以重复使用,可以缓存签名结果,避免重复计算。
- **减少不必要的加密操作**:检查业务逻辑,确保只有在必要时才进行加密和签名操作。

---

### **3. 硬件资源不足**
如果服务器的 CPU 性能不足,或者 PHP 配置不当,可能会导致运算速度变慢。

#### **解决方案**
- **升级硬件**:如果服务器 CPU 性能不足,考虑升级硬件。
- **优化 PHP 配置**:
  - 增加 PHP 的内存限制(`memory_limit`)。
  - 增加 PHP 的最大执行时间(`max_execution_time`)。
  - 启用 `opcache` 以提高 PHP 脚本的执行效率。

---

### **4. 代码优化**
从代码中可以看到,`EncryptPayload` 方法中使用了 `jwsBuilder` 和 `jweBuilder` 进行签名和加密操作。这些操作可能会重复创建对象,导致性能下降。

#### **解决方案**
- **重用对象**:确保 `jwsBuilder` 和 `jweBuilder` 等对象在多次请求中重复使用,而不是每次请求都重新创建。
- **减少不必要的操作**:检查代码逻辑,确保没有不必要的加密或签名操作。

---

### **5. 性能分析**
使用性能分析工具(如 Xdebug 或 Blackfire)来分析代码的执行时间,找出具体的性能瓶颈。

#### **解决方案**
- **安装 Xdebug**:使用 Xdebug 分析代码的执行时间和内存使用情况。
- **使用 Blackfire**:Blackfire 是一个更强大的性能分析工具,可以帮助你找到代码中的性能瓶颈。

---

### **6. 日志和监控**
从代码中可以看到,`sendPrePaymentRequest` 方法中已经记录了错误日志。可以进一步扩展日志记录,监控性能瓶颈。

#### **解决方案**
- **记录性能日志**:在关键操作(如 `EncryptPayload` 和 `DecryptToken`)中添加日志,记录执行时间。
- **监控服务器资源**:使用工具(如 Prometheus 或 New Relic)监控服务器的 CPU、内存和网络使用情况。

---

### **需要进一步检查的内容**
为了进一步分析问题,可以提供以下信息:
1. **RSA 密钥长度**:检查 `SecurityData::$MerchantSigningPrivateKey` 和 `SecurityData::$PacoEncryptionPublicKey` 的密钥长度。
2. **服务器配置**:提供服务器的 CPU、内存配置以及 PHP 的 `php.ini` 配置。
3. **性能日志**:在 `EncryptPayload` 和 `DecryptToken` 方法中添加日志,记录执行时间。

---

### **总结**
你可以从以下几个方面入手解决问题:
1. **检查密钥长度**,确保使用 2048 位的 RSA 密钥或切换到 ECC。
2. **优化代码**,减少不必要的加密和签名操作,并重用对象。
3. **升级硬件**或优化 PHP 配置。
4. **使用性能分析工具**(如 Xdebug 或 Blackfire)定位性能瓶颈。
5. **扩展日志记录**,监控性能瓶颈。




### **1. OPcache 配置优化**
你已经启用了 OPcache,但可以进一步优化其配置,以提高 PHP 脚本的执行效率:

```ini
[opcache]
opcache.enable=1
opcache.memory_consumption=256          ; 增加内存分配,默认 128M 可能不够
opcache.interned_strings_buffer=32      ; 字符串缓存大小,可以增加到 64
opcache.max_accelerated_files=100000    ; 增加缓存文件数量
opcache.revalidate_freq=60              ; 减少重新验证频率,降低 I/O 开销
opcache.fast_shutdown=1                 ; 启用快速关闭
opcache.enable_cli=1                    ; 启用 CLI 模式的 OPcache
opcache.jit_buffer_size=256m            ; 增加 JIT 缓冲区大小
opcache.jit=1255                        ; 启用 JIT 并优化级别

解释

  • opcache.memory_consumption:增加内存分配,确保 OPcache 有足够的内存缓存脚本。
  • opcache.max_accelerated_files:增加缓存文件数量,避免缓存不足。
  • opcache.revalidate_freq:减少脚本重新验证的频率,降低文件系统 I/O 开销。
  • opcache.jit_buffer_size:增加 JIT 缓冲区大小,提升 JIT 编译的性能。

2. 调整 PHP 内存限制

RSA 加密和签名操作可能会消耗较多内存,确保 memory_limit 设置足够大:

memory_limit = 2048M  ; 根据服务器内存情况调整

3. 调整 PHP 执行时间

RSA 操作可能会耗时较长,确保 max_execution_time 设置足够大:

max_execution_time = 600  ; 根据实际需求调整

4. 启用 GMP 扩展

GMP(GNU Multiple Precision Arithmetic Library)是一个用于大数运算的高性能库。如果你的 RSA 操作涉及大数运算,启用 GMP 扩展可以显著提升性能:

extension=gmp.so

5. 减少日志输出

在生产环境中,减少日志输出可以降低 I/O 开销:

error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED
display_errors = Off
log_errors = On

6. 优化 RSA 密钥长度

RSA 密钥长度直接影响加密和签名的性能。确保密钥长度适中:

  • 2048 位:在安全性和性能之间提供良好平衡。
  • 4096 位:安全性更高,但性能较差。

如果密钥长度过大(如 4096 位),考虑切换到 ECC(椭圆曲线加密),它在相同安全级别下性能更好。


7. 缓存 RSA 签名结果

如果某些数据是静态的或可以重复使用,可以缓存签名结果,避免重复计算。例如:

$cacheKey = md5($payload);
if ($cachedResult = $cache->get($cacheKey)) {
    return $cachedResult;
}

$signature = $rsa->sign($payload);
$cache->set($cacheKey, $signature, 3600); // 缓存 1 小时
return $signature;

8. 使用更高效的加密库

如果性能问题依然存在,可以考虑使用更高效的加密库,例如:

  • Libsodium:支持现代加密算法(如 Ed25519 签名),性能优于 RSA。
  • OpenSSL:直接调用 OpenSSL 函数,可能比 PHP 内置的加密函数更快。

9. 性能分析工具

使用性能分析工具(如 XdebugBlackfire)来定位性能瓶颈:

  • Xdebug:分析函数调用和执行时间。
  • Blackfire:提供更详细的性能分析报告。

10. 服务器硬件优化

如果服务器硬件资源不足,考虑以下优化:

  • 升级 CPU:RSA 操作是 CPU 密集型的,升级到更高性能的 CPU 可以显著提升性能。
  • 增加内存:确保服务器有足够的内存支持 PHP 和 OPcache。
  • 使用 SSD:提高文件 I/O 性能,尤其是 OPcache 的脚本缓存。

11. 检查 PHP 版本

确保你使用的是最新的 PHP 版本(如 PHP 8.1 或 PHP 8.2),新版本的 PHP 在性能和安全性方面都有显著提升。


总结

通过以上优化措施,你可以显著提升 PHP 的性能,特别是 RSA 加密和签名操作的效率。如果问题依然存在,可以进一步分析具体的性能瓶颈(如使用 Xdebug 或 Blackfire),并根据分析结果进行针对性优化。


ps: 上面都是ai分析的过程 最后发现安装扩展GMP扩展解决问题
复制全文 生成海报 PHP 加密 性能优化 安全性 开发

推荐文章

Vue3中如何处理跨域请求?
2024-11-19 08:43:14 +0800 CST
关于 `nohup` 和 `&` 的使用说明
2024-11-19 08:49:44 +0800 CST
Vue 中如何处理跨组件通信?
2024-11-17 15:59:54 +0800 CST
Vue3结合Driver.js实现新手指引功能
2024-11-19 08:46:50 +0800 CST
Gin 框架的中间件 代码压缩
2024-11-19 08:23:48 +0800 CST
如何在Rust中使用UUID?
2024-11-19 06:10:59 +0800 CST
Go 1.23 中的新包:unique
2024-11-18 12:32:57 +0800 CST
10个极其有用的前端库
2024-11-19 09:41:20 +0800 CST
Vue 3 路由守卫详解与实战
2024-11-17 04:39:17 +0800 CST
php获取当前域名
2024-11-18 00:12:48 +0800 CST
Linux查看系统配置常用命令
2024-11-17 18:20:42 +0800 CST
Python Invoke:强大的自动化任务库
2024-11-18 14:05:40 +0800 CST
JS中 `sleep` 方法的实现
2024-11-19 08:10:32 +0800 CST
Vue3中如何处理WebSocket通信?
2024-11-19 09:50:58 +0800 CST
Python 基于 SSE 实现流式模式
2025-02-16 17:21:01 +0800 CST
Go语言中的mysql数据库操作指南
2024-11-19 03:00:22 +0800 CST
html夫妻约定
2024-11-19 01:24:21 +0800 CST
程序员茄子在线接单