4、SM2密钥生成:椭圆曲线参数选择、密钥对生成算法、随机数质量对密钥安全的影响
密钥生成,是SM2算法落地的第一道关卡。很多人觉得这步简单,不就是调个库吗?但我在TEE里踩过的坑告诉我——参数选不对,随机数质量不行,后面所有安全假设都是空中楼阁。
咱们这一节,就把密钥生成的三个核心问题掰开揉碎讲清楚:曲线参数怎么选、密钥对怎么算、随机数为什么是命根子。
4.1 椭圆曲线参数:不是随便选个曲线就能用
SM2使用的椭圆曲线是固定的,由国家密码管理局定义。参数包括:p(素数域)、a、b(曲线系数)、G(基点)、n(基点阶)、h(余因子)。
我见过有人图省事,直接拿别的曲线参数替换——结果密钥对生成出来,签名验签死活对不上。说白了,SM2的参数是经过严格验证的,不能乱改。
| 参数 | 含义 | SM2标准值(十六进制) |
|---|---|---|
p |
素数域模数 | FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF |
a |
曲线系数 | FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC |
b |
曲线系数 | 28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93 |
Gx |
基点x坐标 | 32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7 |
Gy |
基点y坐标 | BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0 |
n |
基点阶 | FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123 |
h |
余因子 | 1 |
4.2 密钥对生成算法:从私钥到公钥的数学之旅
SM2密钥对生成,核心就两步:
- 生成私钥:在
[1, n-2]范围内随机选取一个整数d。 - 计算公钥:
P = d * G,即私钥乘以基点。
听起来简单吧?但这里有个坑——私钥不能是0,也不能是n-1。为什么?因为0对应的公钥是无穷远点,n-1对应的公钥和1对称,安全性直接降级。
我习惯在生成后加一步校验:验证d * G是否确实等于P,并且P不在无穷远点上。这步虽然多花几微秒,但能避免很多低级错误。
核心流程:
// 伪代码:SM2密钥对生成
function generateKeyPair():
d = randomBigInt(1, n-2) // 私钥
P = scalarMultiply(d, G) // 公钥
assert P != pointAtInfinity()
assert isOnCurve(P)
return (d, P)
你想想看,如果随机数生成器出了问题,私钥d可能每次都一样——那还谈什么安全?
4.3 随机数质量:密钥安全的命门
这是我最想强调的部分。SM2私钥本质上就是一个随机数。如果随机数可预测,私钥就等于公开了。
在TEE环境中,随机数来源通常有几种:
- 硬件真随机数生成器(TRNG):基于物理噪声,质量最高。
- 伪随机数生成器(PRNG):基于种子,需要定期重新播种。
- 软件随机数:比如
/dev/random,在TEE里可能不可靠。
我建议:优先使用TEE提供的TRNG接口。如果TRNG不可用,至少要用PRNG+硬件熵源混合。千万别直接用软件随机数——我在一个项目里见过,TEE启动初期熵池还没初始化,生成的密钥对居然有规律可循。
4.4 知识体系总览
下面这张图,把密钥生成的核心逻辑串起来了。你可以看到,从参数固化到随机数生成,再到密钥对计算和校验,每一步都环环相扣。
4.5 避坑指南:我踩过的三个雷
最后,分享几个实战中容易翻车的地方:
- 雷区一:随机数种子复用。我曾经在调试阶段为了复现问题,固定了随机数种子。结果上线前忘了改回来——所有设备生成的私钥一模一样。嗯,那次被骂得不轻。
- 雷区二:公钥未校验。生成公钥后,一定要检查它是否在曲线上。攻击者可能通过注入无效曲线点,诱导你泄露私钥信息。
- 雷区三:私钥暴露在TEE边界。私钥生成后,只能在TEE内部使用。我见过有人为了方便,把私钥通过共享内存传出去——那TEE的保护就形同虚设了。
一句话总结:SM2密钥生成,参数选对是基础,算法实现要严谨,随机数质量是底线。这三条缺一条,密钥安全就是空话。