2. SM2 数学基础:椭圆曲线密码学、有限域、基点、阶

说实话,很多搞工程的朋友一听到「椭圆曲线」这四个字,第一反应就是:这是数学家的地盘,我们只管调接口就行。我在带团队时也见过不少人,签名验签用得很顺,但换个曲线参数就懵了。

我的观点很明确:你不需要成为数论专家,但你必须理解那几个核心概念是怎么串起来的。否则,密钥怎么生成的?签名为什么只有 64 字节?这些你心里没底。

这一章我们就来掰开揉碎,把 SM2 背后的数学底牌讲清楚。嗯,我保证不堆公式,尽量用工程人的语言说。

2.1 椭圆曲线:长的不是椭圆,是方程

先纠正一个常见误解。椭圆曲线这个名词跟「椭圆」没有几何关系——它来源于计算椭圆周长的积分。实际上,它是一个长得像这样的方程:
y² = x³ + ax + b。

我们要求判别式 4a³ + 27b² ≠ 0,保证曲线没有尖点和自交。这就像你写代码要保证除数不为零,一个道理。

SM2 用的曲线参数是固定的。a 和 b 已经定义好了,你不用自己选。我刚开始研究国密时,老想着能不能换一组参数试试。后来踩了个坑:参数配错,硬件加速器直接跑飞了。所以,SM2 曲线参数是国标指定的,不能乱动。

SM2 推荐曲线参数(简记)
曲线方程:y² = x³ + ax + b,其中 a = -3(十六进制 0xFFFFFFFE...),b = 0x28E9FA9E...
详细数值请查阅 GMT 0003-2012 标准附录。

工程小贴士:实际开发时,参数通常以 ASN.1 结构体的形式存放在固件中。你只需要调用标准接口,不用手工填写每个值。

2.2 有限域:把实数关进笼子里

刚才那条曲线是在实数域上的。但密码学里不能用实数,因为实数是连续的、无限的,计算机没法精确表示。我们需要一个「有限」的集合。

这就引出了有限域的概念。你可以把它想象成一个整数环,所有运算都在模一个大素数 p 之后进行。SM2 选择的是素数域 GF(p),p 是一个 256 位的质数。

为什么是这个素数?
我的理解是,这个 p 的大小恰好适合 256 位密钥的安全强度,同时还能利用一些特殊结构加速运算。我早年在一个嵌入式项目里,尝试过用 192 位的曲线,结果被评审专家直接否决了——安全强度不够。

于是,所有点的坐标 (x, y) 都是 0 到 p-1 之间的整数。曲线从一条连续的线,变成了一堆离散的点。

2.3 基点与阶:密码系统的锚点

曲线有确定好的一组参数之后,还需要选择一个特殊的起点。这个点叫做基点 G。

基点 G 是 SM2 椭圆曲线群的一个生成元。什么意思?就是你从 G 开始,不断做点加法(G、2G、3G……),能生成曲线上的所有点。

那么,到底能生成多少个不同的点呢?这个数量就是「阶」,记作 n。n 也是一个非常大的素数,和 p 位数差不多。

概念 工程比喻 SM2 中的角色
基点 G 坐标原点 / 基准点 密钥派生起点
阶 n 循环的周期 保证私钥不会重复
素数 p 有限空间的模数 限定坐标范围

警惕!如果 G 的阶 n 不是一个大素数,攻击者可能利用「小子群攻击」来获取你的私钥。SM2 标准已经通过参数选择规避了这个问题,但你在自定义曲线时一定要检查。我就在一个学术项目中见过因为阶太小导致密钥被枚举的案例。

2.4 ECC 上的运算:点加与倍点

椭圆曲线上定义了一种特殊的加法。两个点 P 和 Q 相加,得到曲线上的第三个点 R。算法很简单:过 P 和 Q 作直线,交曲线于第三点,然后关于 x 轴对称。

如果 P 和 Q 是同一个点,那就做切线。这个操作叫做倍点。

在实际软件实现中,我们用的全是这些「点加」和「倍点」的组合。我建议你了解这个流程:

  1. 选取基点 G。
  2. 私钥 d 是一个大整数(随机选取)。
  3. 公钥 Q = d * G(执行 d 次点加)。

这就是 SM2 密钥对生成的全部过程。你想想看,私钥是一个随机整数,公钥是椭圆曲线上的一个点。反过来,要从公钥 Q 反推出私钥 d,就等价于求离散对数,目前没有多项式时间解法——这就是安全性的根本保证。

我曾在面试中问过这个问题:为什么 ECC 可以用更短的密钥达到 RSA 同等的安全强度?说白了,就两个字——离散对数。

2.5 为什么用 ECC?对比 RSA 你就懂了

对比项 ECC(SM2) RSA
安全强度(等效) 256 位 ECC ≈ 3072 位 RSA 密钥长度大,计算慢
签名速度 快(依赖标量乘) 慢(依赖大数模幂)
密钥生成速度 极快(随机数 + 点乘) 慢(需要生成大素数)
存储开销 小(32 字节私钥) 大(数百字节私钥)

这是我自己的经验:在 IoT 设备上,RSA 密钥对生成有时需要几秒钟(甚至更久),而 SM2 基本上毫秒级完成。所以国密选择 ECC 作为签名算法,是有道理的。

2.6 把知识拧成一根绳:本章知识结构

下面这张图能帮你把本章的核心逻辑串起来。我不喜欢死记硬背,所以我做了一幅结构图,用来厘清椭圆曲线、有限域、基点和阶之间的关系。

SM2数学基础核心结构图 SM2数学基础核心结构图 椭圆曲线 E y² = x³ + ax + b 有限域 GF(p) 模 p 整数环 基点 G 与阶 n 生成元 & 循环周期 点集合(离散点) 点加 / 倍点运算 密钥对生成: Q = d * G 私钥 d (随机整数) → 公钥 Q (点) 💡 为什么这张图重要? 椭圆曲线在有限域上形成离散点群。基点 G 的阶 n 决定了私钥的安全空间。 密钥分层管理正是依赖这个结构实现不同用途的密钥隔离。

从图上可以看得很清楚:椭圆曲线方程定义了点的集合,有限域 GF(p) 把这些点限制在整数范围内,基点 G 和它的阶 n 则定义了运算的空间大小。最后,通过点加和倍点运算,我们就能实现安全的密钥对生成。

这么多年来,我一直认为:把这些理解了,你再去研究 SM2 签名和加密的代码,就会发现那些接口参数不是凭空冒出来的,都是有数学依据的。

注意了:图上方的模块缺一不可。如果阶 n 不够大,或者曲线参数 a、b 选择不当,整个系统就不安全。SM2 标准已经把这些都定死了——你直接信任它、使用它,不要自作聪明去改参数。