第3章 常见非对称加密算法:RSA、ECC原理、密钥生成与加解密流程
聊到非对称加密,大家最先想到的基本就是 RSA 和 ECC。RSA 诞生早,应用广,很多老系统还在用。ECC 呢,近十年越来越火,因为它在同等安全强度下密钥短、性能好。我最早接触 RSA 时,被大素数生成那段折腾得不轻,后来发现 OpenSSL 一把梭搞定,心态才平复。今天咱们就把这两兄弟的底裤扒一扒。
3.1 RSA 原理与密钥生成
RSA 的核心是"大整数分解难"。说白了,给你两个大素数 p 和 q 很容易,但把它们的乘积 N 分解回去,计算机做不到。
3.1.1 密钥对怎么来的?
- 随机选两个大素数 p, q(通常 1024 位以上)。
- 计算 N = p × q,φ(N) = (p-1)(q-1)。
- 选一个公钥指数 e,常用 65537,满足 gcd(e, φ(N)) = 1。
- 用扩展欧几里得算法算私钥 d ≡ e⁻¹ mod φ(N)。
- 公钥 = (N, e),私钥 = (N, d)。
我记得第一次手写扩展欧几里得时,递归了几行就把栈写爆了……后来直接调 Python 的 pow(e, -1, phi_n) 就完事。
3.1.2 加解密与签名
| 操作 | 公式 | 说明 |
|---|---|---|
| 加密 | c = m² mod N | m 为明文数字,要求 m < N |
| 解密 | m = cd mod N | 私钥 d 解密 |
| 签名 | s = hashd mod N | 用私钥对哈希签名 |
| 验签 | hash = se mod N | 用公钥验证 |
注意:RSA 加密不能直接加密大块数据,必须做 OAEP 填充。我曾经在项目里直接用裸 RSA 加密一段 JSON,结果被同事怼了——填充不对,密文长度都不固定。
3.2 ECC 原理与密钥生成
ECC 靠的是椭圆曲线上的离散对数难题。说白了,给定曲线上一点 G 和一个大整数 k,计算 K = kG 很容易;但从 K 反推 k 几乎不可能。这就是 ECC 的底气。
3.2.1 曲线参数与密钥生成
标准曲线比如 secp256k1(比特币用的)、P-256(NIST 标准)。参数包括:
- 基域特征 p
- 系数 a, b
- 基点 G
- 阶 n
- 余因子 h
密钥生成步骤:
- 随机选取私钥 d ∈ [1, n-1]。
- 计算公钥 Q = d × G(点乘)。
- 私钥 = d,公钥 = (Q, 曲线参数)。
我的习惯:生成 ECC 密钥时一定要确认所用曲线是否在“受信任列表”里。之前有个项目误用了被攻破的 secp256r1 变种,测试阶段就被安全否决了。
3.2.2 ECDH 密钥交换与 ECDSA 签名
| 协议 | 核心运算 | 典型用途 |
|---|---|---|
| ECDH | 双方分别计算 d₁Q₂ = d₂Q₁ | TLS 握手 |
| ECDSA | 签名: 选随机数 k, r = (kG).x, s = k⁻¹(hash + d·r) | 数字签名 |
| SM2 | 国密曲线,类似 ECDSA | 国内合规 |
3.3 RSA vs ECC 核心对比
| 维度 | RSA | ECC |
|---|---|---|
| 安全基础 | 大整数分解 | 椭圆曲线离散对数 |
| 密钥长度(同等安全) | 2048 位 | 256 位 |
| 运算速度(加密/签名) | 较慢 | 更快 |
| 解密/验签速度 | 比 ECC 略快 | 较慢(点乘重) |
| 密钥生成 | 需要素数检测,较慢 | 直接随机数,很快 |
| 常见应用 | 老旧系统、证书签名 | 移动端、IoT、TLS1.3 |
你如果做单元测试,RSA 密钥对生成大概要 1~2 秒(2048 位),ECC 瞬间就出。所以写集成测试时,我通常把 RSA 密钥生成放 beforeAll,ECC 可以随用随生。
3.4 加解密流程归纳
用一张图说清两个体系:
3.5 避坑与建议
- 密钥长度别省:RSA 至少 2048 位,ECC 至少 256 位(对应 P-256)。我曾经见过测试环境用 512 位 RSA,加密一秒就解开了……那是真·玩具。
- 填充必须对:RSA 加密用 OAEP,签名用 PSS。裸 RSA 等于没穿防弹衣。
- 曲线要认准:ECC 选曲线时不要用随机未知曲线,优先用 NIST 或 SM2 等标准曲线。我记得有个开源库默认用 secp192k1,安全性不够,被评审打了回来。
- 性能测验:单元测试里务必加上时间断言,防止回归引入过慢实现。比如 RSA 签名超过 20ms 就报警。
核心口诀:
RSA 保底,ECC 高效;密钥生成 ECC 秒出;填充选择定生死;曲线合规别踩雷。