第一章 SM2算法基础:国密标准概述、椭圆曲线密码学原理与对比分析

各位同学好,我是老周。做嵌入式安全这行十几年了,今天咱们聊聊SM2。说实话,我第一次接触SM2是在一个政府项目的固件升级模块里——客户指定要用国密,我当时对椭圆曲线还停留在书本上,结果调试时踩了不少坑。嗯,这节课我就把这些经验揉碎了讲给你听。

1.1 国密标准概述:SM2在国密家族中的位置

国密算法是国家密码管理局发布的一套商用密码标准。SM2是其中的公钥密码算法,2010年发布,2017年正式成为国家标准(GB/T 32918)。

我习惯把国密家族比作一个工具箱:

  • SM2:公钥加密、数字签名、密钥协商——相当于工具箱里的扳手和螺丝刀
  • SM3:密码杂凑算法,输出256位摘要——相当于工具箱里的卷尺
  • SM4:对称分组密码算法,密钥长度128位——相当于工具箱里的锁
  • SM9:基于标识的密码算法——相当于工具箱里的万能钥匙

在固件保护场景里,SM2主要负责签名验证和密钥分发。你想想看,如果固件被篡改了,SM2的签名验证就是最后一道防线。

核心要点:SM2不是单独使用的,在固件保护方案中,通常用SM2做签名,SM3做哈希,SM4做对称加密。三者配合才能形成完整的防护链。

1.2 SM2椭圆曲线密码学原理

椭圆曲线密码学(ECC)的核心,说白了就是在一个有限域上的椭圆曲线点群上做离散对数运算。SM2使用的是256位的素域椭圆曲线。

为什么选椭圆曲线?因为它的安全强度高,密钥短。160位的ECC和1024位的RSA安全等级相当,但计算量小得多。在嵌入式设备上,这点优势太重要了——我做过一个项目,MCU只有几百KB的Flash,跑RSA 2048签名验证要好几秒,换成SM2后降到几百毫秒。

SM2的曲线参数

SM2使用的椭圆曲线方程为:y² = x³ + ax + b,其中a和b是固定参数。具体参数由国家密码管理局定义,包括:

  • 素数p:256位的大素数
  • 系数a和b:曲线方程系数
  • 基点G:生成元
  • 阶n:基点G的阶
  • 余因子h:通常为1

这些参数是公开的,但私钥是随机选取的大整数d,公钥P = d * G。你想想看,知道P和G求d,就是椭圆曲线离散对数问题——目前没有多项式时间算法能解。

避坑指南:我曾经在移植SM2库时,发现曲线参数写错了几个字节,结果签名验证一直失败。排查了两天才找到问题。所以,曲线参数一定要从官方标准中复制,不要手打,不要从不可靠的网站复制。

SM2的密钥对生成

生成SM2密钥对的步骤很简单:

  1. 随机生成一个256位的整数d,作为私钥
  2. 计算公钥P = d * G,其中G是基点
  3. 输出密钥对(d, P)

在固件保护中,私钥通常存储在安全芯片或HSM中,公钥则嵌入到固件中用于验证签名。

1.3 SM2与RSA/ECC的对比分析

很多同学问我:SM2和RSA到底哪个好?我的回答是:看场景。但如果你做的是嵌入式固件保护,我强烈推荐SM2。

下面这张表是我根据多年项目经验整理的对比:

对比维度 SM2 (ECC) RSA 传统ECC (secp256k1等)
密钥长度 256位 2048位 256位
签名速度 快 慢 快
验证速度 较快 快 较快
安全强度 128位 112位 128位
算法公开性 国标公开 国际公开 国际公开
国内合规性 强制要求 部分场景受限 部分场景受限
嵌入式适配 优秀 一般 优秀

从表中可以看出,SM2在密钥长度和签名速度上优势明显。但要注意,RSA的验证速度比SM2快——这在某些场景下是优势,比如服务器端需要频繁验证签名时。

重要提醒:不要因为SM2是国标就盲目使用。如果你的产品需要出口到某些国家,可能需要同时支持SM2和RSA。我遇到过客户要求固件同时支持两种签名算法,结果Flash空间差点不够用。

SM2 vs 传统ECC

SM2本质上是一种ECC,但它和比特币用的secp256k1、NIST P-256有什么不同?

  • 曲线参数不同:SM2的曲线参数是中国人自己设计的,不是NIST的曲线
  • 签名算法不同:SM2的签名算法是改进的ECDSA,加入了用户标识等参数
  • 密钥格式不同:SM2的公钥和私钥格式遵循国标规范
  • 合规性不同:在国内商用密码应用中,SM2是强制要求

我个人习惯在项目初期就确定使用哪种曲线。因为一旦固件中嵌入了公钥,后期更换曲线意味着要重新签名所有固件,工作量很大。

1.4 SM2在固件保护中的核心流程

为了让你更直观地理解SM2在固件保护中的作用,我画了一张流程图:

SM2固件签名验证流程 SM2固件签名验证流程 固件签名(开发阶段) 原始固件二进制 SM3哈希计算 SM2私钥签名 生成签名值(r, s) 打包:固件 + 签名 + 公钥 固件验证(设备端) 接收固件包 提取固件、签名、公钥 SM3哈希计算 SM2公钥验证签名 验证通过?执行 / 拒绝 说明:私钥存储在安全环境(HSM/安全芯片),公钥嵌入固件Bootloader 设备端只做验证操作,不接触私钥

这张图展示了SM2在固件保护中的完整流程。左侧是开发阶段,右侧是设备端验证阶段。注意看,私钥始终在安全环境中,设备端只做验证操作——这是最基本的安全原则。

1.5 实战中的注意事项

最后,分享几个我在项目中踩过的坑:

  • 随机数质量:SM2签名需要高质量的随机数。我曾经用了一个伪随机数生成器,结果签名值出现了重复,差点被攻击者利用。建议使用硬件随机数发生器。
  • 密钥存储:公钥嵌入固件时,要加上校验机制。我见过有人直接把公钥放在固件头部,结果被攻击者替换了公钥,导致任意固件都能通过验证。
  • 性能优化:在低端MCU上,SM2签名验证可能耗时较长。可以考虑预计算部分点乘结果,或者使用硬件加速模块。
  • 合规性:如果产品需要过国密局检测,必须使用经过认证的SM2实现库,不能自己实现。

个人经验:我在一个物联网项目中,把SM2签名验证放在Bootloader里,每次启动时验证固件完整性。但Bootloader空间有限,SM2的代码体积又大。最后我用了代码裁剪,只保留验证功能,去掉了签名生成和密钥生成代码,体积缩小了60%。