密码学数学基础(上):群、环、域与椭圆曲线

说实话,很多做国密开发的工程师,一听到「数学基础」四个字就想绕道走。我早年带团队做 SM2 签名性能优化时,有个同事把椭圆曲线上的点加写成了坐标直接相加,结果验签死活过不去。排查了两天才发现——他压根没搞懂「群律」是什么。

所以这一章,咱们把数学底子打扎实。不扯虚的,直接讲你写代码时真正用得上的东西。

1. 群、环、域:密码学的三块积木

这三个概念是抽象代数的核心。我个人的理解方式很简单:它们就是定义了「你能对集合里的元素做什么操作」的规则集。

1.1 群(Group)

群是最基础的结构。一个集合 G 配上一种运算 ·,满足四个条件:

  • 封闭性:a·b 还在 G 里
  • 结合律:(a·b)·c = a·(b·c)
  • 单位元:存在 e,使得 e·a = a·e = a
  • 逆元:每个 a 都有 a⁻¹,使得 a·a⁻¹ = e

我的经验:SM2 签名算法中,私钥 d 就是一个大整数,它所在的集合是「模 n 的整数乘法群」。你写代码时如果发现签名结果不对,先检查私钥是否在 [1, n-2] 范围内——不在群里的元素,运算结果毫无意义。

如果运算还满足交换律(a·b = b·a),就叫交换群(阿贝尔群)。椭圆曲线上的点加群就是交换群,这一点后面会用到。

1.2 环(Ring)

环比群多一种运算。一个集合 R 配上加法和乘法,满足:

  • 加法构成交换群
  • 乘法满足封闭性、结合律
  • 乘法对加法有分配律:a·(b+c) = a·b + a·c

整数集合 Z 就是最典型的环。SM4 算法中 S 盒的构造用到了 GF(2⁸) 上的多项式环,本质上就是环结构。

1.3 域(Field)

域是环的升级版——乘法也要能求逆(除了加法单位元 0)。也就是说,域里每个非零元素都有乘法逆元。

有理数 Q、实数 R、复数 C 都是域。但密码学里用的不是这些——我们用有限域。

2. 有限域:GF(p) 与 GF(2ⁿ)

有限域,顾名思义,元素个数是有限的。这个个数叫域的阶。密码学里只用两种:

类型元素个数典型应用
GF(p)p(大素数)SM2 椭圆曲线基域
GF(2ⁿ)2ⁿSM4 S盒、AES

2.1 GF(p):素数域

GF(p) 的元素是 {0, 1, 2, ..., p-1},加减乘除都在模 p 下进行。p 必须是素数,否则非零元素不一定有逆元。

关键点:SM2 国密标准中,椭圆曲线方程 y² = x³ + ax + b 的系数 a、b 和坐标 x、y 都是 GF(p) 中的元素。p 是 256 位的大素数,具体值在 GMT 0003-2012 里写死了。

举个例子,GF(7) 里:

3 + 5 = 8 mod 7 = 1
4 × 6 = 24 mod 7 = 3
2⁻¹ = 4,因为 2 × 4 = 8 mod 7 = 1

嗯,这里要注意:求逆元不能用除法直接算,得用扩展欧几里得算法。我见过有人直接用浮点数除法再取整,结果可想而知。

2.2 GF(2ⁿ):二进制域

GF(2ⁿ) 的元素是 n 位二进制串,可以看成系数在 GF(2) 上的多项式。加减法就是按位异或(XOR),乘法是多项式乘法再模一个不可约多项式。

为什么用 GF(2ⁿ)?因为硬件实现极快——加法连门电路都不用,一根 XOR 门搞定。SM4 的 S 盒就是基于 GF(2⁸) 构造的。

我曾经踩过的坑:GF(2ⁿ) 里的加法是 XOR,不是整数加法。有次做 SM4 优化,我把两个字节的 S 盒输出直接相加,结果扩散性全乱套。记住:在二进制域里,1 + 1 = 0,不是 2。

3. 椭圆曲线方程与群律

国密 SM2 使用的椭圆曲线方程是:

y² = x³ + ax + b   (mod p)

其中 4a³ + 27b² ≠ 0 (mod p),保证曲线没有奇点(尖点或自交)。

曲线上所有点(包括一个特殊的「无穷远点」O)构成一个交换群。群运算就是「点加」。

3.1 点加(Point Addition)

给定曲线上两个不同的点 P(x₁, y₁) 和 Q(x₂, y₂),P + Q = R(x₃, y₃) 的计算公式:

λ = (y₂ - y₁) / (x₂ - x₁)   (mod p)
x₃ = λ² - x₁ - x₂           (mod p)
y₃ = λ(x₁ - x₃) - y₁        (mod p)

这里除法是模 p 下的乘法逆元。我习惯先算 λ,再算 x₃,最后算 y₃,三步走不容易出错。

3.2 倍点(Point Doubling)

当 P = Q 时,就是 P + P = 2P:

λ = (3x₁² + a) / (2y₁)     (mod p)
x₃ = λ² - 2x₁               (mod p)
y₃ = λ(x₁ - x₃) - y₁        (mod p)

性能建议:SM2 签名验签中,倍点运算占了计算量的 60% 以上。我建议用 Jacobian 投影坐标系代替仿射坐标系,省掉模逆运算,速度能快 3-5 倍。具体实现可以参考 GMT 0003 附录。

4. 点的阶与循环子群

椭圆曲线上一个点 P 的阶,就是最小的正整数 n,使得 nP = O(无穷远点)。

举个例子,如果 P 的阶是 7,那么:

P, 2P, 3P, 4P, 5P, 6P, 7P = O

这 7 个点(包括 O)构成一个循环子群。SM2 签名用的就是这样一个循环子群,阶记为 n,是一个大素数。

4.1 为什么阶必须是素数?

你想想看,如果子群的阶 n 是合数,比如 n = p × q,那攻击者就可以用 Pohlig-Hellman 算法,把离散对数问题分解到小阶子群里去解。这就是为什么 SM2 标准要求 n 是素数,且 n 要足够大(256 位)。

核心结论:SM2 的安全性建立在「椭圆曲线循环子群上的离散对数问题」的难解性上。子群的阶 n 越大、越接近素数,破解难度就越高。国密标准选的曲线,n 等于一个 256 位素数,安全强度约 128 比特。

5. 知识体系总览

下面这张图把本章的核心逻辑串起来了:

密码学数学基础(上)知识体系 群 (Group) 环 (Ring) 域 (Field) 有限域 (Finite Field) GF(p) 素数域 GF(2ⁿ) 二进制域 椭圆曲线 E: y² = x³ + ax + b 点加 + 倍点(群律) 点的阶与循环子群 SM2 签名/验签/密钥交换 注意 子群阶 n 必须是素数 且 ≥ 256 位

6. 小结与避坑指南

这一章的内容,说白了就是一句话:SM2 的数学基础 = 有限域 GF(p) + 椭圆曲线群律 + 大素数阶循环子群。

最后分享几个我实际踩过的坑:

  • 模逆运算别用试除法:GF(p) 里求逆元一定要用扩展欧几里得算法,或者用费马小定理 a^(p-2) mod p。试除法在 256 位素数下跑一次要几秒钟,完全不可用。
  • 检查点是否在曲线上:SM2 验签第一步就是验证接收到的公钥点 Q 是否满足曲线方程。我见过有人跳过这步,结果被无效点攻击打穿。
  • 无穷远点的处理:O 是群的单位元,P + O = P。代码里要单独判断,不能直接套点加公式(分母会为零)。

重要提醒:千万不要在生产代码里自己实现椭圆曲线运算。国密 GMT 0003-2012 标准里已经给出了完整的算法描述和测试向量。用标准库,别造轮子——除非你像我一样,为了搞懂原理手写过一遍,但写完就扔,别上线。