开篇: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密钥边界设计的核心原则
这部分是咱们这门课的基石。搞明白它,后面的代码才不会写偏。
- 密钥生成必须符合国标曲线——参数错了,后面全白搭。
- 私钥必须安全存储——不能明文写在Flash里。
- 公钥需要验证合法性——防止伪造公钥攻击。
- 密钥生命周期管理——生成、使用、更新、销毁,每一步都要有记录。
我见过不少新手,密钥生成出来就直接怼上去跑,结果公钥验证没做,被中间人攻击了都不知道怎么回事。
避坑指南:SM2的公钥是一个点(x, y)。这个点必须在曲线上!怎么验证?代入曲线方程算一遍就行。我曾经因为忘了这一步,debug了整整两天。
一张图看懂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的核心组件:签名、加密、密钥交换,各自有各自的边界约束。
嗯,这些就够了。
后面的章节我们会逐块深入,从密钥生成代码开始,一步步把边界设计落地。