1. SM2 算法概述:国密标准背景、椭圆曲线原理与 RSA/ECC 对比
各位同学,咱们今天开篇聊聊 SM2。说实话,我在做国密改造项目之前,对 SM2 的印象也就是「国产的 ECC」。直到真正在 TEE 里把它跑起来,才发现这里面的门道比想象中多得多。
先交代一下背景。SM2 是国家密码管理局在 2010 年发布的椭圆曲线公钥密码算法标准,标准号 GM/T 0003-2012。你想想看,那时候国际上 RSA 和 ECC 已经非常成熟了,为什么我们还要自己搞一套?说白了,密码算法这东西,核心基础设施不能完全依赖别人。我记得有一次跟客户聊,他们金融系统里原来全是 RSA 1024,后来发现国际上有些标准组织开始弃用 1024 位密钥,逼着他们升级。这时候 SM2 的优势就出来了——它直接对标 256 位 ECC 的安全强度,一步到位。
核心要点: SM2 不是从零发明的密码算法,而是基于国际公认的椭圆曲线密码体制(ECC),在曲线参数、签名流程、密钥格式上做了国标化定制。它的安全基础是椭圆曲线离散对数问题(ECDLP),这一点跟 ECC 完全一致。
1.1 椭圆曲线密码算法原理——我尽量讲得不枯燥
椭圆曲线长什么样?数学上定义是 y² = x³ + ax + b,其中 4a³ + 27b² ≠ 0。别被公式吓到,你把它想象成一条在二维平面上弯弯曲曲的曲线就行。SM2 用的是 Fp 上的素域椭圆曲线,参数是固定的,不像 ECC 那样可以自己选曲线。
为什么椭圆曲线能用来做密码?因为曲线上两个点相加,结果还在曲线上,而且这个加法运算满足群公理。更关键的是,给定一个基点 G 和一个整数 k,计算 k * G 很容易;但反过来,给你两个点 G 和 Q,让你找出 k 使得 Q = k * G,这就难了。这就是椭圆曲线离散对数问题(ECDLP)。
我在项目中遇到过一件事:有个同事把 SM2 的私钥长度搞错了,以为跟 RSA 2048 一样是 2048 位。其实 SM2 私钥只有 256 位,公钥是 512 位(未压缩格式)。你想想看,256 位的私钥就能提供跟 RSA 3072 同等级别的安全强度,这就是椭圆曲线的魅力。
避坑指南: 我曾经在移植 SM2 库时,忽略了椭圆曲线点压缩格式的处理。SM2 公钥默认是未压缩格式(04 开头 + x 坐标 + y 坐标),但有些硬件模块只支持压缩格式(02 或 03 开头 + x 坐标)。如果你在 TEE 里做密钥导入导出,一定要确认两端的格式约定,否则会踩坑。
1.2 SM2 与 RSA、ECC 的对比分析
咱们直接上表格,这样对比最直观。我习惯把这三个算法放在一起看,因为很多客户会问:「你们为什么不用 RSA?ECC 不是国际标准吗?SM2 到底好在哪?」
| 对比维度 | SM2 | RSA | ECC(国际标准) |
|---|---|---|---|
| 安全基础 | ECDLP(椭圆曲线离散对数) | 大整数分解(IFP) | ECDLP |
| 密钥长度(同等安全强度) | 256 位 | 3072 位 | 256 位 |
| 签名速度 | 快(约 2-3ms) | 慢(约 10-20ms) | 快(约 2-3ms) |
| 验签速度 | 较快(约 5-8ms) | 快(约 1-2ms) | 较快(约 5-8ms) |
| 密钥生成速度 | 极快 | 慢 | 极快 |
| 算法标准化 | 国标 GM/T 0003 | PKCS#1 / FIPS 186 | SECG / NIST / ISO |
| 国内合规性 | 强制要求(等保、密评) | 不推荐(部分场景禁用) | 允许但需配合国密 |
| TEE 适配难度 | 中等(需国密库支持) | 低(几乎所有 TEE 原生支持) | 低(TEE 原生支持) |
从表格能看出来,SM2 和 ECC 在性能上几乎一致,因为底层数学原理相同。区别在于曲线参数和签名算法细节。SM2 的签名算法跟 ECDSA 不一样,它用的是类似 Schnorr 签名的变体,签名输出是两个 256 位的整数 (r, s),而不是 ECDSA 那种 DER 编码格式。
RSA 呢?它的优势是验签快,而且生态极其成熟。但密钥太长,生成慢,在资源受限的 TEE 环境里其实不太友好。我做过一个测试:在 ARM TrustZone 里生成 RSA 2048 密钥对,平均耗时 3-5 秒;而 SM2 密钥生成只需要几十毫秒。差距非常明显。
注意: 不要因为 SM2 和 ECC 性能相近,就认为可以直接用 ECC 库替换 SM2。SM2 的曲线参数是国标固定的(p、a、b、G、n 都是特定值),签名流程也有差异。我曾经见过有人把 ECDSA 的签名结果直接当成 SM2 签名传给国密网关,结果验签失败。嗯,这个坑我踩过。
1.3 SM2 算法体系全景图
下面这张图是我自己整理的 SM2 算法体系结构。你把它当成一张地图,后面几章我们会逐个模块深入。
这张图把 SM2 拆成了三层:上层是三个功能模块(签名、密钥交换、加密),中间是底层数学支撑,下层是密钥管理和 TEE 适配。后面几章我们会逐个击破。我个人建议你先记住这个结构,后面讲到具体模块时,随时回来对照,思路会清晰很多。
1.4 为什么在 TEE 里用 SM2?
这个问题我经常被问到。其实答案很简单:合规 + 安全。等保 2.0 和密评都要求关键系统使用国密算法,SM2 是必选项。而 TEE 提供了硬件隔离的执行环境,SM2 的私钥可以安全地存储在 TEE 内部,普通世界(REE)根本访问不到。
我在一个金融项目中,把 SM2 签名模块跑在 ARM TrustZone 的安全世界里。用户发起交易时,明文数据通过共享内存传给安全世界,安全世界调用 SM2 签名,签名结果再传回普通世界。整个过程私钥从未离开 TEE。嗯,这才是正确的做法。
经验之谈: 如果你刚开始接触 SM2 在 TEE 里的实现,我建议先不要急着写代码。先把 SM2 的曲线参数(p、a、b、G、n)搞清楚,再理解签名和验签的流程。我在培训新人时,发现 80% 的问题都出在对曲线参数的理解上。比如 SM2 的基点 G 的坐标是固定的,跟 secp256k1 不一样,千万别搞混。
好了,第一章就到这里。SM2 的概貌你应该有了。记住:它本质上就是一条椭圆曲线,加上国标定制的参数和流程。后面我们会深入每个模块,包括在 TEE 里怎么安全地存储私钥、怎么加速椭圆曲线运算、怎么避免侧信道攻击。这些才是真正考验工程师功底的地方。