3、RSA签名性能测试:不同密钥长度下的吞吐量对比
RSA 的密钥长度,说白了就是安全性和性能之间的博弈。密钥越长,破解难度指数级上升,但签名和验签的速度也会肉眼可见地变慢。这一章,我们就用实际数据说话,看看 1024、2048、4096 位密钥下,RSA 的吞吐量到底差了多少。
3.1 测试环境与工具
先交代一下我的测试环境。机器是 Intel Xeon Gold 6248R,3.0GHz,32 核,内存 128GB。操作系统是 Ubuntu 22.04 LTS,内核 5.15。OpenSSL 版本是 3.0.8,编译时开启了硬件加速(AES-NI 和 AVX2)。
测试工具我用了 OpenSSL 自带的 speed 命令,以及自己写的一个多线程压测脚本。为什么不用纯 OpenSSL speed?因为它只测单线程,而实际生产环境往往是多并发的。所以我额外用 C 语言 + pthread 写了一个压测程序,模拟 16 个并发客户端同时请求签名和验签。
核心测试命令:
# 单线程基准测试
openssl speed rsa1024 rsa2048 rsa4096
# 多线程压测(自定义脚本)
./rsa_bench -key 2048 -threads 16 -duration 60 -mode sign
./rsa_bench -key 2048 -threads 16 -duration 60 -mode verify
3.2 单线程基准测试结果
先看单线程下的原始数据。OpenSSL speed 会报告每秒能完成的签名和验签次数。我跑了三次取平均值,结果如下:
| 密钥长度 | 签名 (ops/s) | 验签 (ops/s) | 签名/验签比值 |
|---|---|---|---|
| 1024 位 | 12,845 | 48,231 | 1 : 3.75 |
| 2048 位 | 2,136 | 12,987 | 1 : 6.08 |
| 4096 位 | 312 | 3,456 | 1 : 11.08 |
看到这个数据,你可能会问:为什么验签比签名快这么多?
嗯,这里有个关键点。RSA 签名用的是私钥,验签用的是公钥。私钥指数 d 通常很大(接近模数 n 的位数),而公钥指数 e 一般固定为 65537(0x10001),这个数二进制只有两个 1,模幂运算快得飞起。所以验签天然比签名快一个数量级。
我的经验: 我在项目中遇到过有人把签名和验签搞反了——用公钥去签名,结果慢得离谱。记住:私钥签名,公钥验签,别搞混。
3.3 多线程并发压测结果
单线程数据只能反映算法本身的性能。实际生产环境,比如 API 网关、证书签发服务,都是多线程并发的。所以我用 16 个线程同时压测,看看吞吐量如何变化。
| 密钥长度 | 签名 (ops/s) | 验签 (ops/s) | CPU 利用率 |
|---|---|---|---|
| 1024 位 | 98,432 | 372,160 | 92% |
| 2048 位 | 16,872 | 98,560 | 88% |
| 4096 位 | 2,496 | 27,648 | 76% |
多线程下,吞吐量基本是单线程的 8 倍左右,没有达到 16 倍线性扩展。为什么?因为 RSA 运算本身是 CPU 密集型的,内存带宽和缓存争抢会限制扩展比。4096 位的 CPU 利用率只有 76%,说明计算单元已经喂不饱 CPU 了——每次运算的数据量太大,缓存命中率下降,内存延迟成了瓶颈。
避坑指南: 我曾经在压测 4096 位 RSA 时,发现吞吐量上不去,以为是代码问题。后来用 perf 一看,L3 缓存缺失率高达 40%。4096 位的密钥和中间结果占用了大量缓存,多线程下互相驱逐,性能自然上不去。所以,如果你要用 4096 位,建议减少并发线程数,或者用 NUMA 绑核。
3.4 不同密钥长度的选型建议
数据摆在这里,怎么选?我个人的习惯是:
- 1024 位: 别用了。NIST 早在 2010 年就建议弃用,现在用 1024 位基本等于裸奔。除非你是在维护十年前的遗留系统,否则别碰。
- 2048 位: 当前的主流选择。安全强度够用(等效于 112 位对称密钥),性能也还能接受。大部分 HTTPS 证书、JWT 签名、代码签名都在用这个长度。
- 4096 位: 安全强度更高(等效于 128 位对称密钥),但性能代价很大。签名速度只有 2048 位的 1/7,验签速度也只有 1/4。除非你是在做根 CA 证书、或者对安全有极端要求的场景,否则不推荐。
一句话总结: 2025 年的今天,默认选 2048 位。如果性能敏感,可以考虑 ECDSA(后面章节会讲)。如果安全敏感,上 4096 位之前先算好你的 QPS 预算。
3.5 核心逻辑流程图
下面这张图总结了 RSA 签名验签的性能影响因素和选型路径。你可以把它当作一个决策参考。
3.6 性能瓶颈分析
从上面的数据可以看出,RSA 的性能瓶颈主要在签名操作上。为什么签名这么慢?
说白了,RSA 签名就是一次私钥指数 d 的模幂运算。d 的大小和模数 n 差不多,都是 1024/2048/4096 位。这么大的指数做模幂,计算量是 O(n³) 级别的。而验签用的公钥指数 e=65537,二进制只有 17 位,计算量小得多。
我举个例子你就明白了。2048 位 RSA,签名需要做大约 2048 次模乘(用 Montgomery 约减优化后),而验签只需要做 17 次模乘。差了 120 倍。虽然实际有各种优化(CRT、滑动窗口等),但差距依然在 6 倍左右。
优化思路: 如果你发现签名性能是瓶颈,可以考虑用硬件加速卡(如 Intel QAT、AWS Nitro),或者切换到 ECDSA。ECDSA 的签名速度比 RSA 2048 快 5-10 倍,而且密钥更短。后面章节我会专门讲。
3.7 小结
这一章我们通过实际测试数据,看到了 RSA 不同密钥长度下的性能差异。核心就三点:
- 密钥越长越安全,但性能下降明显。2048 位是当前的最佳平衡点。
- 验签永远比签名快,因为公钥指数固定为 65537。
- 多线程下,4096 位的缓存效率问题会进一步放大性能差距。
选型时,别只看安全强度,一定要结合你的 QPS 要求和硬件条件。我见过太多项目,拍脑袋选了 4096 位,结果上线后 CPU 被打满,最后不得不回退到 2048 位。嗯,提前做性能测试,比事后救火强得多。