第1章 SM2算法概述
国密算法背景
先说说国密算法是干嘛的。说白了,就是咱们国家自己的一套密码标准。早些年,国内很多系统用的都是国外的算法,比如RSA、ECC这些。但你想,密码这东西可是命门,用别人的算法总归不放心。
我记得在2018年,参与某政务云项目时,甲方明确要求所有敏感数据必须使用国密算法。当时我就在想,这玩意儿得尽早熟悉起来。果不其然,后来金融、电力、医疗等行业陆续出台政策,国密算法几乎成了硬性门槛。
国密算法体系里,有几个关键成员:
- SM2 — 椭圆曲线公钥密码算法,用于签名和加密
- SM3 — 密码杂凑算法,类似SHA-256
- SM4 — 分组密码算法,对标AES
我们今天重点聊的SM2,就是这套体系里的核心。它基于椭圆曲线密码学(ECC),但在具体参数和实现上,跟国际上的ECDSA、ECIES不太一样。
SM2标准介绍
SM2的标准编号是GM/T 0003-2012,后来更新到了2016版。它包含三个部分:数字签名算法、密钥交换协议、公钥加密算法。我们要讲的分层管理,主要涉及签名和加密这两块。
我习惯把SM2的密钥分成两种角色:
- 签名密钥 — 用于生成数字签名,验证身份真实性。私钥必须严格保密。
- 加密密钥 — 用于加密数据,保证机密性。私钥也需保密,但使用场景不同。
你可能会问:既然都是SM2的密钥对,为什么要分开管?我在项目中就遇到过这种情况——直接用同一对密钥又签名又加密。结果呢?签名密钥需要频繁使用,暴露风险高;一旦泄露,加密的数据也全完了。这叫做密钥使用范围混淆,是安全设计的大忌。
SM2算法的核心
SM2的本质还是椭圆曲线算法。它定义了一条特定的椭圆曲线:
y² = x³ + ax + b
其中参数a和b是固定的。SM2选用的曲线称为sm2p256v1,其参数如下:
| 参数 | 值 | 说明 |
|---|---|---|
| p | FFFFFFFE FFFFFFFF ... (256位) | 素数域模数 |
| a | FFFFFFFE FFFFFFFF ... (256位) | 曲线系数 |
| b | 28E9FA9E 9D9F5E34 ... (256位) | 曲线系数 |
| G | 两个坐标点 (x, y) | 基点,用于生成密钥 |
| n | FFFFFFFE FFFFFFFF ... (256位) | 基点的阶 |
你可能觉得这些参数看着头疼。没关系,你只需要记住一个核心:密钥对的生成过程。
私钥就是一个随机数d,范围在[1, n-2]之间。公钥就是私钥乘以基点G,即P = d * G。这个计算过程是单向的,从私钥算公钥很容易,但反过来基本不可能(椭圆曲线离散对数问题)。
SM2的密钥架构
既然要分层管理,就得先看看密钥长什么样。SM2密钥对包含:
- 私钥 — 一个256位的随机整数
- 公钥 — 一个点坐标 (x, y),各256位,总共512位
公钥的存储格式通常有两种:未压缩格式(完整64字节)和压缩格式(32字节+1个标记位)。
在分层管理时,我习惯把密钥分为三层:
- 主密钥(MK) — 根密钥,用于派生其他密钥
- 签名子密钥(SK_sig) — 专用于数字签名
- 加密子密钥(SK_enc) — 专用于数据加密
为什么要这样分?因为不同密钥的使用频率、安全要求、生命周期都不一样。签名密钥可能每天被调用上千次,而加密密钥可能一年才换一次。混在一起管理,很容易出事。
实践中的几点注意
光知道理论不够。我结合项目经验,列几个实际中容易出问题的地方:
- 密钥长度别搞错 — SM2私钥是256位,不是128位也不是512位。曾经有同事拿SM4的密钥来当SM2用,结果签名验证一直过不去。
- 随机数质量要保证 — 私钥生成依赖强随机数。别用rand()这种伪随机,建议用硬件随机数或系统提供的加密级随机源。
- 公钥校验不能省 — 收到对方公钥时,先验证它是否在曲线上,否则可能被注入无效曲线攻击。