椭圆曲线密码学(ECC)基础:有限域、椭圆曲线方程、点加与标量乘法
好,咱们进入正题。这一章是 ECC 的根基,说白了就是搞明白三个东西:有限域是什么、椭圆曲线方程长什么样、点加和标量乘法怎么算。
我刚开始接触 ECC 时,觉得这玩意儿挺玄乎。后来踩了几个坑才明白,其实核心逻辑并不复杂。你想想看,ECC 的安全性本质上就是靠「在有限域上做椭圆曲线点加」这个操作来撑着的。
2.1 有限域:ECC 的「数字沙盘」
先聊有限域。为什么需要它?
实数域上的椭圆曲线是连续的,图像很漂亮。但密码学里不能用连续的东西——计算机算不了无限精度的小数,而且实数域上的离散对数问题太好解了。我们需要一个「离散」的、元素个数有限的集合,这就是有限域。
核心定义:有限域 Fp 是一个包含 p 个元素的集合,p 是素数。所有运算(加、减、乘、除)都在模 p 下进行。
举个例子,F7 包含 {0,1,2,3,4,5,6}。在 F7 里,5 + 6 = 4(因为 11 mod 7 = 4),3 × 4 = 5(12 mod 7 = 5)。
我个人习惯把有限域想象成一个「数字沙盘」——所有操作都被限制在这个沙盘里,出不去。ECC 就在这个沙盘上画椭圆曲线。
| 域类型 | 表示 | 元素个数 | 典型应用 |
|---|---|---|---|
| 素数域 | Fp | p(大素数) | secp256k1、P-256 |
| 二进制域 | F2m | 2m | Curve25519(部分实现) |
| 扩域 | Fpm | pm | 配对友好曲线 |
避坑指南:我曾经在实现 ECC 时,忘记把中间结果模 p,导致点坐标越界,算出来的点根本不在曲线上。调试了整整两天才发现。记住:有限域上的每一步运算都要模 p,包括中间结果。
2.2 椭圆曲线方程:Weierstrass 标准型
ECC 用的曲线方程长这样:
y² = x³ + ax + b (mod p)
其中 a、b 是有限域 Fp 中的常数,且满足 4a³ + 27b² ≠ 0 (mod p)——这个条件保证曲线没有奇点(没有尖点或自交)。
为什么用这个方程?说白了,它满足「群结构」的要求。曲线上任意两点做「点加」运算,结果还在曲线上。这个性质是 ECC 能用于密码学的前提。
关键参数:
- p:素数,决定有限域大小
- a, b:曲线系数
- G:基点(生成元),曲线上一个公开的点
- n:基点 G 的阶(最小的 n 使得 nG = O,O 是无穷远点)
- h:余因子(cofactor),通常为 1 或小整数
举个例子,比特币用的 secp256k1 曲线参数:
p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
a = 0
b = 7
G = (0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8)
n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
h = 1
你看,a=0,b=7,所以曲线方程就是 y² = x³ + 7。简单吧?但简单不代表不安全。
2.3 点加运算:ECC 的「加法」
点加是 ECC 最核心的运算。两个曲线上的点 P 和 Q,相加得到第三个点 R。
几何意义(在实数域上理解):
- 过 P 和 Q 画一条直线
- 这条直线与曲线相交于第三个点 R'
- R' 关于 x 轴对称的点就是 R = P + Q
代数公式(在有限域 Fp 上):
设 P = (x₁, y₁), Q = (x₂, y₂), P ≠ Q, P ≠ -Q
斜率 λ = (y₂ - y₁) / (x₂ - x₁) (mod p)
x₃ = λ² - x₁ - x₂ (mod p)
y₃ = λ(x₁ - x₃) - y₁ (mod p)
如果 P = Q(点倍乘),斜率公式变成:
λ = (3x₁² + a) / (2y₁) (mod p)
注意:除法在有限域里是乘以模逆元。比如 λ = (y₂ - y₁) * (x₂ - x₁)⁻¹ mod p。我见过不少新手直接写除法,结果跑出来全是错的。记住:有限域里没有「除法」这个操作,只有「乘以逆元」。
2.4 标量乘法:ECC 的「核心武器」
标量乘法就是 kP,其中 k 是一个整数,P 是曲线上的点。计算方法是重复点加:
kP = P + P + ... + P (k 次)
但 k 可能是个 256 位的数,直接加 k 次要算到猴年马月。实际用的是 双倍-加算法(Double-and-Add):
输入:k = (kₙ₋₁ ... k₁ k₀)₂, 点 P
输出:kP
Q = O (无穷远点)
for i from n-1 down to 0:
Q = 2Q // 点倍乘
if kᵢ == 1:
Q = Q + P // 点加
return Q
这个算法的时间复杂度是 O(log k),对于 256 位的 k,只需要 256 次点倍乘和平均 128 次点加。效率非常高。
个人经验:我在做嵌入式 ECC 实现时,发现双倍-加算法有个隐患——时间侧信道攻击。如果每次循环都判断 kᵢ 是否为 1,攻击者可以通过测量运算时间来推断 k 的比特位。后来我改用 Montgomery Ladder,运算时间恒定,才解决了这个问题。
2.5 知识体系总览
下面这张图把本章的核心逻辑串起来了。我建议你多看几遍,把每个模块之间的关系理清楚。
2.6 为什么 ECC 比 RSA 更「省」?
这个问题我经常被问到。答案就在标量乘法里。
RSA 的安全性基于大整数分解,密钥长度需要 2048 位以上。ECC 的安全性基于 ECDLP,256 位的密钥就能提供同等安全强度。为什么?因为目前已知最好的 ECDLP 攻击算法(Pollard's rho)的复杂度是 O(√n),而大整数分解的复杂度是亚指数级的。
| 安全等级 | RSA 密钥长度 | ECC 密钥长度 | 性能优势 |
|---|---|---|---|
| 80 位 | 1024 | 160 | ECC 快 3-5 倍 |
| 128 位 | 3072 | 256 | ECC 快 5-10 倍 |
| 256 位 | 15360 | 512 | ECC 快 10-20 倍 |
一句话总结:ECC 用更短的密钥、更少的计算量,达到和 RSA 同等的安全强度。这就是它成为现代密码学主流的原因。