密码学基础回顾:有限域与椭圆曲线
说实话,很多工程师一上来就撸SM2的代码,结果在密钥对生成那一步就卡住了。为什么?因为没搞懂背后的数学结构。我当年也是踩过这个坑的——直接调库当然能跑,但一旦遇到跨平台互调、性能优化或者硬件适配,不懂原理根本没法debug。
这一章,咱们就把SM2依赖的密码学基础捋一遍。不扯太深的理论,够用就行。
2.1 有限域:SM2的“数字沙盘”
有限域,说白了就是一个元素个数有限的集合,里面的数可以做加减乘除,结果还在这个集合里。SM2用的是素域Fp,p是一个大素数。
核心概念:SM2的椭圆曲线定义在Fp上,p = 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF
这个p有256位。为什么选这个数?我个人的理解是:它既保证了安全性,又方便硬件实现——你看它的二进制形式,大部分位都是1,做模运算时可以优化。
有限域上的运算规则很简单:
- 加法:a + b mod p
- 乘法:a × b mod p
- 逆元:a × a-1 ≡ 1 mod p
我的经验:在嵌入式设备上实现SM2时,模逆运算最耗性能。我曾经用费马小定理 ap-2 mod p 来计算逆元,虽然慢但通用。后来换成扩展欧几里得算法,速度提升了3倍。
2.2 椭圆曲线:SM2的“几何舞台”
SM2使用的椭圆曲线方程是:
y² = x³ + ax + b (mod p)
其中参数a和b是固定的:
| 参数 | 值(十六进制) |
|---|---|
| a | 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC |
| b | 0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93 |
嗯,这里要注意:SM2的曲线参数是国标规定的,不能自己随便改。我在项目里见过有人从网上复制了错误的参数,结果签名验证一直失败——折腾了两天才发现是b参数写错了一位。
椭圆曲线上的点,就是满足这个方程的所有(x, y)对,再加上一个特殊的“无穷远点”O。
2.3 点加运算:曲线上的“加法”
椭圆曲线上的点加法,不是普通坐标相加。它有一套几何规则:
- 过点P和Q画一条直线
- 这条直线与曲线交于第三点R'
- R'关于x轴的对称点就是P+Q的结果
公式长这样(别怕,实际代码里都是现成的):
设 P = (x₁, y₁), Q = (x₂, y₂), P ≠ Q
λ = (y₂ - y₁) / (x₂ - x₁) mod p
x₃ = λ² - x₁ - x₂ mod p
y₃ = λ(x₁ - x₃) - y₁ mod p
避坑指南:我曾经在实现点加时,忘记处理P=Q的情况(倍点)和P=-Q的情况(结果为无穷远点)。这两个边界条件不处理,密钥对生成就会随机出错,而且很难复现。
倍点(P=P的情况)公式略有不同:
λ = (3x₁² + a) / (2y₁) mod p
x₃ = λ² - 2x₁ mod p
y₃ = λ(x₁ - x₃) - y₁ mod p
2.4 标量乘法:密钥生成的核心
标量乘法就是:k × P = P + P + ... + P(k次)。
但你不能真的加k次——k是256位的数,加2²⁵⁶次得算到宇宙毁灭。实际用的是“双倍-加”算法:
function scalar_mult(k, P):
R = O // 无穷远点
for i from 255 down to 0:
R = double(R) // 倍点
if bit_i_of_k == 1:
R = add(R, P) // 点加
return R
这个算法只需要256次倍点和平均128次点加,效率高得多。
性能优化:我在做SM2硬件加速时,发现可以用“窗口法”进一步优化——把k分成4位一组,预计算16个点,每次查表。这样点加次数减少到64次,速度提升明显。
2.5 密钥对生成原理
终于到正题了。SM2密钥对生成其实就三步:
- 选私钥:在[1, n-1]范围内随机选一个整数d,n是曲线的阶(也是一个固定的大素数)
- 算公钥:P = d × G,G是曲线的基点
- 输出:私钥d,公钥P
基点的坐标也是国标规定的:
Gx = 0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7
Gy = 0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0
为什么公钥不能从私钥反推?因为标量乘法是“单向”的——知道d和G算P很容易,但知道P和G反推d,就是椭圆曲线离散对数问题,目前没有多项式时间算法。
安全要点:随机数生成器必须真随机。我曾经见过一个项目,用C语言的rand()生成私钥,结果每次启动私钥都一样——这等于没加密。SM2标准推荐使用国家密码管理局认可的随机数发生器。
2.6 本章知识体系
下面这张图把本章的核心逻辑串起来了:
这张图从下往上看:有限域是地基,椭圆曲线是建筑,基点是入口,标量乘法是电梯,密钥对是顶层房间。每一步都依赖前一步,缺一不可。
2.7 小结
这一章我们走完了从有限域到密钥对的完整路径。说白了,SM2的密码学基础就是三件事:
- 在有限域上定义椭圆曲线
- 用点加和倍点实现标量乘法
- 用标量乘法从私钥算出公钥