开篇:SM2算法究竟是什么?

说实话,第一次接触SM2的时候,我也有点懵。

那时候刚做完一个RSA的项目,客户突然说“要用国密”。我心想,国密不就是换几个参数吗?结果一上手才发现,这玩意儿跟RSA完全是两码事。今天这一章,我们就来把这个“两码事”彻底聊明白。

SM2的出身:国密标准里的扛把子

SM2是中国国家密码管理局发布的椭圆曲线公钥密码算法标准。
它属于椭圆曲线密码体制(ECC)家族,但跟我们熟悉的secp256k1(比特币用的那个)不一样——SM2有一套自己的参数体系。

标准编号 内容 发布年份
GB/T 32918.1-2016 总则 2016
GB/T 32918.2-2016 数字签名算法 2016
GB/T 32918.3-2016 密钥交换协议 2016
GB/T 32918.4-2016 公钥加密算法 2016
GB/T 32918.5-2017 参数定义 2017

说白了,SM2不是单个算法,是一整套解决方案。
签名、加密、密钥交换,全包了。我当年在项目中就吃过这个亏——只实现了签名,客户问“加密呢?”只好连夜加班补上。

核心要点:SM2 = 椭圆曲线 + 国标参数 + 三个密码原语(签名/加密/密钥交换)

为什么是椭圆曲线?

你想想看,RSA靠的是大整数分解,ECC靠的是椭圆曲线离散对数问题。两者都是数学难题,但ECC有个天然优势:密钥短,安全性高。

安全强度(比特) RSA密钥长度 ECC密钥长度 SM2密钥长度
80 1024 160 —
112 2048 224 —
128 3072 256 256
256 15360 512 —

看到没?SM2用256位密钥就能达到128位安全强度。RSA需要3072位。
我刚开始做SM2的时候,总觉得256位太短了,不安全。后来实测了一把——想多了。

我的经验:在实际项目中,密钥长度直接决定了硬件资源消耗。SM2的256位密钥在嵌入式设备上优势巨大,尤其是那些只有几十KB内存的MCU。

SM2与RSA、ECDSA的对比

很多人问我:“SM2跟ECDSA有啥区别?”
嗯,这个问题问得好。

  • SM2的签名算法跟ECDSA不一样。SM2用的是改进型的Schnorr签名,不是ECDSA那种。
  • SM2的密钥交换协议支持双方认证,而传统ECDH只是简单协商。
  • SM2的加密算法用了KDF(密钥派生函数),输出是定长的。

注意:我曾经踩过一个坑——直接用OpenSSL的ECDSA代码,改了曲线参数就当SM2用。结果是签名验证死活过不去。SM2的签名流程里有个“签名者身份标识ZA”的参与,ECDSA里根本没有这回事。

SM2密钥边界设计的核心原则

这部分是咱们这门课的基石。搞明白它,后面的代码才不会写偏。

  1. 密钥生成必须符合国标曲线——参数错了,后面全白搭。
  2. 私钥必须安全存储——不能明文写在Flash里。
  3. 公钥需要验证合法性——防止伪造公钥攻击。
  4. 密钥生命周期管理——生成、使用、更新、销毁,每一步都要有记录。

我见过不少新手,密钥生成出来就直接怼上去跑,结果公钥验证没做,被中间人攻击了都不知道怎么回事。

避坑指南:SM2的公钥是一个点(x, y)。这个点必须在曲线上!怎么验证?代入曲线方程算一遍就行。我曾经因为忘了这一步,debug了整整两天。

一张图看懂SM2算法体系

SM2算法知识结构图 SM2 算法知识结构 椭圆曲线基础 secp256r1 ≠ SM2曲线 SM2算法 国标椭圆曲线参数 国密标准 GB/T 32918.x-2016 密钥生成 私钥 d ∈ [1, n-2] 数字签名 包含标识符 ZA 公钥加密 KDF + 密文流 密钥交换 双方认证协商 密钥边界设计原则 生成 → 存储 → 验证 → 生命周期 SM2不是单个算法,而是一组基于椭圆曲线的密码原语体系

与其他公钥算法的本质区别

你可能听过“ECC比RSA快”,这个说法不够准确。
我的测试结果是:SM2签名比RSA-2048快3-5倍,但验签速度差不多。加密方面,SM2比RSA慢一点点,因为要做KDF和点乘。

算法 签名速度 验签速度 加密速度 密钥长度
RSA-2048 慢(~20次/秒) 快(~200次/秒) 快 2048位
ECDSA(P-256) 快(~100次/秒) 慢(~30次/秒) 不支持原生加密 256位
SM2 快(~120次/秒) 中(~40次/秒) 支持 256位

注意:上数字是我在ARM Cortex-M4上跑的实测值。PC上会快更多,但相对比例差不多。

选型建议:如果你只需要签名,ECDSA和SM2都行。但如果你需要加密,SM2是唯一自带原生加密的ECC方案。RSA虽然也支持加密,但密钥太长,在资源受限的环境里很尴尬。

一个小代码示例:SM2密钥生成

这里给个伪代码意思一下,真实项目里我们会用硬件TRNG来做随机数。
但核心逻辑是一样的:

// SM2密钥生成伪代码
输入:无
输出:私钥d,公钥P

1. 生成随机数 d,范围 [1, n-2]
   // n是SM2曲线的阶(国家规定)
2. 计算公钥点 P = d * G
   // G是基点,也是国家规定的
3. 验证P是否在曲线上
   // 代入方程 y² = x³ + ax + b
4. 返回 (d, P)

看到没?就这么几行。但实际实现中,每一步都有坑。
比如步骤2的点乘运算,如果没做侧信道防护,密钥就可能被偷走。

重要:步骤3的公钥验证不能省!我接手过一个项目,对方直接在步骤2之后返回P,结果有次生成的点不在曲线上,签名验签全乱套了。

这一章能给你什么?

  • 搞清楚了SM2不是RSA的替代品,而是另一条技术路线。
  • 明白了密钥边界设计不是孤立的,必须绑定制曲线参数一起考虑。
  • 知道了SM2的核心组件:签名、加密、密钥交换,各自有各自的边界约束。

嗯,这些就够了。
后面的章节我们会逐块深入,从密钥生成代码开始,一步步把边界设计落地。