非对称加密算法 SM2 介绍归纳总结
说到国密算法,SM2 是我项目里打交道最多的一个。我第一次接触它是在给某金融机构做身份认证模块的时候,当时还在纳闷——为什么不用现成的 ECDSA 非要自己搞一套?后来深入看了 SM2 的标准文档,才明白它在参数选择和安全边界上确实花了不少心思。说白了,SM2 就是中国版的椭圆曲线公钥密码体系,但它不是简单抄国外标准,而是针对实际工程做了很多调整。
椭圆曲线基础——为什么选它?
你想想看,传统的 RSA 随着密钥长度增加,性能下降特别快。椭圆曲线密码(ECC)能用更短的密钥达到同等安全强度,比如 SM2 的 256 位密钥强度大致相当于 RSA 3072 位。我个人习惯用一句话给团队新人解释:SM2 就是在椭圆曲线这个“有限域加法群”上做文章,通过离散对数难题保证安全性。
我记得有一次给客户做方案汇报,对方问:“同样是 256 位,SM2 比 RSA 安全吗?” 我当时的回答是:“从攻破成本来看,SM2 比 RSA 更划算,因为同样的攻破时间,SM2 的密钥长度只有 RSA 的十分之一不到。” 当然这只是一个工程判断,具体还得看实际攻击模型。
SM2 算法族:不止是签名
SM2 不是一个单一算法,它包含三类核心操作:数字签名、公钥加密和密钥交换。很多刚接触的人以为“SM2 = 签名”,其实公钥加密和密钥交换在分层架构里也非常关键,尤其在构建密钥分发链路时。
- SM2-Sign:用于身份认证和防抵赖。我见过不少项目只拿它做登录验签,其实证书签发、审计日志也可以用它。
- SM2-Encrypt:用于数据加密传输。它用的是“椭圆曲线集成加密方案(ECIES)”的思想,不是直接加密大文件,而是生成对称密钥后再加密数据。
- SM2-KeyExchange:双方安全协商会话密钥。我在做物联网终端密钥分发时发现,这个功能比预置对称密钥更灵活——不用预先共享秘密,只需要各自持有 SM2 密钥对。
密钥对生成与参数选择——容易踩的坑
SM2 的密钥对生成逻辑不复杂:选取一条椭圆曲线(标准里指定了 y² = x³ + ax + b,其中 a 和 b 是固定值),再选一个基点 G,私钥是一个随机大整数 d,公钥 P = d*G。但这里有一个容易忽略的地方——随机数质量。
rand() 生成私钥,结果测试时发现两个设备生成了相同的公钥。排查下来是随机数种子不够随机。从此以后我强制要求使用硬件真随机数或者经过 NIST 测试的 CSPRNG。
另外,SM2 的曲线参数是固定公开的,不像某些国外标准允许自定义曲线。这样做的好处是避免了“后门曲线”的争议,但也意味着你没法根据自己的场景优化曲线性能。嗯,这里要接受“一组参数满足所有场景”的约定。
数字签名(SM2-Sign)——不只是验签
SM2 签名的流程跟 ECDSA 很像,但有一个关键区别:它引入了用户标识 ZA(由用户 ID 和曲线参数计算得来),把签名绑定了用户身份。举个例子,同一个私钥签出来的消息,如果用于不同用户 ID,签名值完全不一样。我记得有一次对接第三方系统,他们没算 ZA 就直接调用验签,结果验签一直失败——花了一天时间对标准文档才发现。
验签时要注意消息的哈希过程。SM2 使用 SM3 哈希,这一步不能省略。我之前遇到过有同事为了“提高性能”直接用 SHA256 替换 SM3,结果符合算法规范,但不符合国密合规要求。所以,合规性也是工程选型的重要一环。
公钥加密(SM2-Encrypt)——混合加密的艺术
SM2-Encrypt 本质是混合加密体系:先用 SM2 公钥加密一个随机生成的对称密钥(K),再用 SM3 派生密钥和 SM4 加密实际数据。这种分离的好处是:非对称部分只处理短密钥,对称部分负责大块数据,性能比纯 RSA 加密高出一个数量级。
我在一个视频监控加密网关项目里用过 SM2-Encrypt 作为会话密钥的传输载体:摄像头端生成临时对称密钥,用网关的 SM2 公钥加密后发送,网关用私钥解密后得到对称密钥,后续数据用 SM4 对称加密。这样既解决了密钥分发问题,又保证了传输性能。
密钥交换(SM2-KeyExchange)——适合无初始凭证的场景
SM2-KeyExchange 实现的是双方的密钥协商,不需要预共享秘密。我在做智能门锁与手机配网时用过:门锁和手机各自生成临时 SM2 密钥对,互相交换公钥,然后各自计算共享密钥。整个过程不需要在线证书中心,但前提是双方都能验证对方的公钥真实性(比如通过扫码等方式)。
协议细节就不展开了,只说一个工程提示:密钥交换完成后,必须删除临时私钥,否则存在密钥泄露风险。我曾经在开发板上做过测试,如果忘记清理内存中的临时私钥,通过简单的内存 dump 就能恢复,所以安全擦除这一步千万别省。
SM2 与密钥分层架构的衔接
在国密密钥分层架构里,SM2 一般出现在两个位置:一是 根密钥层(主密钥对),用于签发下级证书或派生存储密钥;二是 工作密钥层,用于实体的身份认证和会话密钥协商。如下图所示,SM2 的三种算法分别支撑不同的安全边界。
三种算法的工程对比
在实际项目里,我经常需要向决策者解释“为什么不能只用签名”之类的问题。下面这张表总结了 SM2 三种算法的核心差异,方便快速对照选型。
| 维度 | SM2-Sign | SM2-Encrypt | SM2-KeyExchange |
|---|---|---|---|
| 主要用途 | 身份认证、数据防抵赖 | 小数据加密、密钥分发 | 会话密钥协商 |
| 输入输出 | 消息 → (r,s) 签名值 | 明文 → C1||C2 | 双方公钥 ← 共享密钥 |
| 是否需要预共享证书 | 需要验签方持有签名者公钥 | 需要接收方私钥才能解密 | 不需要(临时密钥) |
| 性能开销 | 一次点乘 + 一次求逆(签名) | 两次点乘(加密) | 两次点乘(每方) |
| 常见错误 | 未计算 ZA 导致验签失败 | C1 格式不兼容 | 临时私钥未及时清除 |
做个小结:SM2 不仅是一个签名算法,而是一个完整的非对称密码工具箱。你在设计密钥分层架构时,可以根据安全边界选择合适的算法组合。比如根密钥层适合用 SM2-Sign 做证书签发,应用层可以用 SM2-Encrypt 做数据加密通道,而设备间的密钥协商可以靠 SM2-KeyExchange 来灵活实现。我个人觉得,把这些算法理解成“积木”而不是“黑盒”,才能在复杂系统中游刃有余。