4. SM2推荐曲线参数与验证

SM2 的公钥密码体制并不是“随便选一条椭圆曲线就能用”。国家标准 GB/T 32918 给出了推荐曲线,它由一组固定参数共同定义。理解这些参数的含义、掌握参数合法性检查方法、弄清点压缩与解压缩的编码规则,并警惕工程中参数注入带来的风险,是把 SM2 用对、用安全的前提。

一、推荐曲线参数的含义

SM2 推荐曲线定义在素域 Fp 上,其方程形式为 y² = x³ + ax + b。一条可用的曲线需要以下参数共同确定:

  • p:有限域的素数模数,决定坐标的取值范围,所有坐标运算都在模 p 下进行。
  • a、b:曲线方程系数。SM2 推荐曲线中 a = -3(即 p-3),b 为固定常数。
  • n:基点 G 的阶,即满足 nG = O(无穷远点)的最小正整数,它决定私钥和标量乘法的取值范围。
  • G = (xG, yG):基点,是生成公钥的固定起点,公钥 P = dG,d 为私钥。
  • h:余因子,h = #E(Fp)/n,SM2 推荐曲线 h = 1,意味着曲线阶恰好等于 n,不存在小子群攻击隐患。

这些参数不是孤立的数字,而是彼此约束:p 决定域,a、b 决定曲线形状,G 必须落在曲线上,n 必须是 G 的阶,h 必须为整数。任何一项被篡改,整条曲线就可能退化,安全性随之崩塌。

二、参数合法性检查

在工程实现中,尤其是从外部导入曲线参数时,必须做合法性检查。核心检查项包括:

  1. p 是否为素数,且满足推荐曲线规定的位长(SM2 为 256 位)。
  2. 判别式非零:4a³ + 27b² ≠ 0 (mod p),否则曲线奇异,不构成椭圆曲线群。
  3. 基点 G 在曲线上:验证 yG² ≡ xG³ + a·xG + b (mod p)。
  4. n 为素数,且 nG = O,确保 G 的阶正确。
  5. 余因子 h = 1,或至少验证 h 与推荐值一致。
  6. 参数与国家标准一致:若使用推荐曲线,应逐字节比对 p、a、b、G、n,防止“看似相同实则被替换”。
检查顺序建议:先验 p 的素性与位长,再验判别式,再验 G 在曲线上,最后验 n 与 nG = O。前一步不通过,后续检查没有意义。

三、曲线点压缩与解压缩

椭圆曲线点 (x, y) 中,y 由 x 和曲线方程确定,只差一个正负号。因此可以只传 x 加一个标志位,把点从 65 字节压缩到 33 字节,这就是点压缩。

压缩编码规则:首字节为 0x02 表示 y 为偶数,0x03 表示 y 为奇数,后接 32 字节的 x 坐标。解压缩时,先由 x 代入方程求出 y² = x³ + ax + b (mod p),再用模 p 平方根算法(如 Tonelli-Shanks)求出 y,最后根据首字节的奇偶标志选择正确的 y 值。

压缩点:02/03 || x            (33 字节)
解压缩:
  y2 = x^3 + a*x + b mod p
  y  = sqrt(y2) mod p
  若 (y & 1) 与标志位不符,则 y = p - y
  验证 (x, y) 在曲线上,否则拒绝

解压缩后必须重新验证点是否在曲线上,否则可能引入无效点攻击。压缩点常用于证书、密钥交换报文中节省带宽,但解压缩的每一步都要做边界与合法性判断。

四、工程中的参数注入风险

参数注入是指攻击者通过替换、篡改曲线参数,使系统在一条弱曲线或恶意曲线上运算,从而泄露私钥或伪造签名。典型场景包括:

  • 曲线替换:把推荐曲线换成一条阶很小或结构已知的曲线,使离散对数易解。
  • 基点替换:保持 p、a、b 不变,但把 G 换成低阶点,导致私钥落在小子群中。
  • 无效点注入:在密钥交换中传入不在曲线上的点,触发异常或泄露信息。
  • 参数来源不可信:从配置文件、网络或第三方库加载曲线参数,未做校验。
防御原则:优先使用内置的国标推荐曲线常量,不接受运行时外部传入的曲线参数;若必须导入,则执行完整的合法性检查,并对点做“在曲线上”验证与子群检查。
SM2 推荐曲线参数体系与验证链 曲线参数 p :域素数(256 位) a = -3,b :曲线系数 G = (xG, yG) :基点 n :基点阶(素数) h = 1 :余因子 方程:y² = x³ + ax + b 合法性检查 ① p 素性 + 位长 ② 4a³+27b² ≠ 0 ③ G 在曲线上 ④ n 素性 + nG = O ⑤ h = 1 ⑥ 与国标常量逐字节比对 点压缩 / 解压缩 压缩:02/03 ‖ x 65 字节 → 33 字节 解压:y² = x³+ax+b 求模平方根得 y 按奇偶标志选 y 再验点是否在曲线上 参数注入风险与防御 曲线替换 换成弱曲线 基点替换 低阶点 / 小子群 无效点注入 点不在曲线上 参数来源不可信 外部导入未校验 防御:内置国标常量 · 完整合法性检查 · 点在曲线上验证 · 子群检查 · 拒绝外部未校验参数

把上述内容串起来看:参数定义决定曲线身份,合法性检查确认曲线可用,点压缩与解压缩处理点的编码传输,参数注入防御保证运行时不偏离推荐曲线。四者环环相扣,任何一环放松,SM2 的安全性都无法保证。工程实现中,最稳妥的做法是直接使用标准常量,把校验逻辑作为导入参数的强制关卡,而不是可选项。