第3章 常见非对称加密算法:RSA、ECC原理、密钥生成与加解密流程

聊到非对称加密,大家最先想到的基本就是 RSA 和 ECC。RSA 诞生早,应用广,很多老系统还在用。ECC 呢,近十年越来越火,因为它在同等安全强度下密钥短、性能好。我最早接触 RSA 时,被大素数生成那段折腾得不轻,后来发现 OpenSSL 一把梭搞定,心态才平复。今天咱们就把这两兄弟的底裤扒一扒。

3.1 RSA 原理与密钥生成

RSA 的核心是"大整数分解难"。说白了,给你两个大素数 p 和 q 很容易,但把它们的乘积 N 分解回去,计算机做不到。

3.1.1 密钥对怎么来的?

  1. 随机选两个大素数 p, q(通常 1024 位以上)。
  2. 计算 N = p × q,φ(N) = (p-1)(q-1)。
  3. 选一个公钥指数 e,常用 65537,满足 gcd(e, φ(N)) = 1。
  4. 用扩展欧几里得算法算私钥 d ≡ e⁻¹ mod φ(N)。
  5. 公钥 = (N, e),私钥 = (N, d)。

我记得第一次手写扩展欧几里得时,递归了几行就把栈写爆了……后来直接调 Python 的 pow(e, -1, phi_n) 就完事。

3.1.2 加解密与签名

操作公式说明
加密c = m² mod Nm 为明文数字,要求 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

密钥生成步骤:

  1. 随机选取私钥 d ∈ [1, n-1]。
  2. 计算公钥 Q = d × G(点乘)。
  3. 私钥 = 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 核心对比

维度RSAECC
安全基础大整数分解椭圆曲线离散对数
密钥长度(同等安全)2048 位256 位
运算速度(加密/签名)较慢更快
解密/验签速度比 ECC 略快较慢(点乘重)
密钥生成需要素数检测,较慢直接随机数,很快
常见应用老旧系统、证书签名移动端、IoT、TLS1.3

你如果做单元测试,RSA 密钥对生成大概要 1~2 秒(2048 位),ECC 瞬间就出。所以写集成测试时,我通常把 RSA 密钥生成放 beforeAll,ECC 可以随用随生。

3.4 加解密流程归纳

用一张图说清两个体系:

RSA 与 ECC 加解密流程对比 RSA 流程 1. 生成 p, q, N, e, d 2. 加密: c = me mod N 3. 解密: m = cd mod N 4. 签名: s = hashd mod N 5. 验签: hash = se mod N ECC 流程 1. 选曲线、生成 d, Q=dG 2. ECDH: 共享密钥 = d₁Q₂ 3. ECDSA 签名: (r,s) 4. ECDSA 验签 5. 私钥 d,公钥 Q RSA 依赖大数模幂,ECC 依赖椭圆曲线点乘——核心操作不同,但都能实现加密/签名

3.5 避坑与建议

  • 密钥长度别省:RSA 至少 2048 位,ECC 至少 256 位(对应 P-256)。我曾经见过测试环境用 512 位 RSA,加密一秒就解开了……那是真·玩具。
  • 填充必须对:RSA 加密用 OAEP,签名用 PSS。裸 RSA 等于没穿防弹衣。
  • 曲线要认准:ECC 选曲线时不要用随机未知曲线,优先用 NIST 或 SM2 等标准曲线。我记得有个开源库默认用 secp192k1,安全性不够,被评审打了回来。
  • 性能测验:单元测试里务必加上时间断言,防止回归引入过慢实现。比如 RSA 签名超过 20ms 就报警。
核心口诀:

RSA 保底,ECC 高效;密钥生成 ECC 秒出;填充选择定生死;曲线合规别踩雷。