非对称加密基础:RSA与ECC归纳总结
嗯,说实话,刚入行那会儿,我觉得对称加密够用了。直到第一次做多端通信协议,发现密钥分发简直是个噩梦。你想想,几百个客户端,每个都得预先部署一样的密钥,泄露了还得更新——太折腾了。
非对称加密解决了这个痛点。公钥随便发,私钥自己藏。今天我们就来盘一盘 RSA 和 ECC 这两个主角。
1. 核心思想:一对密钥,各司其职
非对称加密,说白了就是「一个加密,一个解密,不能反推」。公钥加密的数据,只有私钥能解开。反过来,私钥签名的数据,公钥能验证真伪。
我个人习惯把公钥比作「锁」,私钥是「钥匙」。锁可以复制一大堆发给别人,钥匙只有我自己有。别人用锁锁上箱子,只有我能打开。
关键概念:公钥加密、私钥解密;私钥签名、公钥验签。这两个方向是不同的操作,底层依赖的数学难题也不一样。
下面这张图把 RSA 和 ECC 的数学根基、密钥生成、使用场景理清了。我在做身份认证项目时,就是拿着这张图跟产品经理对齐思路的。
2. RSA:老牌悍将,仍有江湖地位
RSA 的历史太长了,1977年就提出来了。它的安全性基于一个很朴素的数学事实:两个大质数相乘容易,但把它们的乘积分解回去极难。
2.1 密钥生成与加解密
选两个大质数 p 和 q,算出 n = p×q。然后找一个 e 满足 gcd(e, φ(n)) = 1,最后算出 d 使得 e×d ≡ 1 mod φ(n)。公钥就是 (n, e),私钥是 (n, d)。
# Python 示例:RSA 密钥生成与加解密(仅演示核心逻辑)
import random
from math import gcd
# 小素数演示,实际用大数
p, q = 61, 53
n = p * q
phi = (p-1) * (q-1)
# 选公钥指数 e,常用 65537
e = 17
while gcd(e, phi) != 1:
e += 2
# 计算私钥 d 的模逆
d = pow(e, -1, phi)
print(f"公钥: (n={n}, e={e})")
print(f"私钥: (n={n}, d={d})")
# 加解密
plaintext = 42
ciphertext = pow(plaintext, e, n)
decrypted = pow(ciphertext, d, n)
print(f"明文: {plaintext}, 密文: {ciphertext}, 解密: {decrypted}")
要记住一个大数幂模运算在超大密钥下非常慢。我记得有一个项目用 RSA-4096 做握手,每次服务端要算几秒,用户体验极差。
实战建议:RSA 主要用于交换对称密钥或数字签名,不要拿它直接加密业务数据。尤其注意 OAEP 填充,教科书的教科书 RSA 加密是不安全的。
2.2 RSA 签名
签名本质是「私钥加密,公钥解密验证」。不过实际用的是哈希+填充,不是直接对消息签名。常用的有 RSASSA-PSS 和 RSASSA-PKCS1-v1_5。
3. ECC:后起之秀,性能王者
ECC 出来得晚一些,1985年才提出,但潜力巨大。它的安全基础是椭圆曲线上的离散对数问题。
3.1 曲线方程与密钥长度
一条椭圆曲线长这样:y² = x³ + ax + b(外加一个无穷远点)。给定基点 G 和私钥 k,公钥 Q = kG。从 Q 和 G 反推 k 是计算上不可行的。
你看,同样的安全强度,ECC 的密钥长度短得多。1024 位 RSA ≈ 160 位 ECC;2048 位 RSA ≈ 224 位 ECC;4096 位 RSA ≈ 384 位 ECC。这带来的直接好处是运算更快、存储更小、通信带宽更低。
| 安全等级 | RSA 密钥长度(位) | ECC 密钥长度(位) | 性能差异(ECC vs RSA) |
|---|---|---|---|
| 90 位 | 1024 | 160 | 快约 5~10 倍 |
| 128 位 | 3072 | 256 | 快约 10~50 倍 |
| 256 位 | 15360 | 521 | 快约 100 倍 |
避坑指南:我曾经在一个 IoT 设备上用了 secp256r1 曲线,结果发现芯片的硬件加速只支持 Curve25519,最后性能还不如 RSA。不能只看理论速度,还要看硬件生态的支持。
3.2 ECC 的典型应用:ECDH 与 ECDSA
ECDH(椭圆曲线 Diffie-Hellman)用来协商对称密钥,双方各生成临时密钥对,交换公钥,各自算出相同的共享秘密。ECDSA(椭圆曲线数字签名算法)则是签名验签的标准方案。
# Python 示例:使用 cryptography 库进行 ECDH 密钥协商
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import serialization
# Alice 生成密钥对
alice_private = ec.generate_private_key(ec.SECP256R1())
alice_public = alice_private.public_key()
# Bob 生成密钥对
bob_private = ec.generate_private_key(ec.SECP256R1())
bob_public = bob_private.public_key()
# 各自计算共享密钥
alice_shared = alice_private.exchange(ec.ECDH(), bob_public)
bob_shared = bob_private.exchange(ec.ECDH(), alice_public)
print(f"双方共享密钥一致: {alice_shared == bob_shared}")
注意,这里算出来的共享密钥是原始字节,不能直接用。我建议再走一步 HKDF(基于 HMAC 的密钥派生函数),把共享密钥派生出真正的对称密钥。
4. 选型建议:场景决定一切
我一般按下面这把尺子来选:
- 兼容性优先:老系统、旧浏览器、政府项目,老老实实用 RSA。2048 位起步,别用 1024 了,已经被破解演示了。
- 性能/资源敏感:移动端、IoT、高并发服务,我建议优先选择 ECC。尤其 Curve25519(X25519 密钥交换 + Ed25519 签名),安全性高、速度快、实现也简单。
- 签名场景:ECC 签名短、生成快,适合交易签名、证书签发。但要注意,有些设备对 ECC 签名验签的硬件支持不够好。
- 密钥交换:ECDHE(临时 ECDH)主流中最佳选择,支持前向安全性。RSA 做密钥交换还行的,但不支持前向安全。
总结:RSA 是传统好用的瑞士军刀,ECC 是新一代的高速跑车。理解它们的数学根基和性能特征,你才能在真实项目中做出最合适的选择。别盲目追求「更高更快更强」,要结合你的部署环境、硬件限制和合规要求。
好了,这一章就到这里。下次我们聊「对称与非对称的混合加密方案」,那是实战中最常见的玩法。到时候我会多讲一些坑,都是我踩过的……