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
注意:在TEE环境中,曲线参数必须固化在安全存储区。我曾经遇到一个案例,参数从外部传入,结果被篡改成了弱曲线——攻击者直接算出了私钥。所以,参数一定要在TEE内部硬编码,或者用安全通道加载并校验哈希。

4.2 密钥对生成算法:从私钥到公钥的数学之旅

SM2密钥对生成,核心就两步:

  1. 生成私钥:在[1, n-2]范围内随机选取一个整数d。
  2. 计算公钥: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启动初期熵池还没初始化,生成的密钥对居然有规律可循。

实战技巧:生成私钥后,可以做一个简单的随机性测试:检查连续多个私钥的汉明重量分布是否均匀。如果发现大量私钥的二进制表示中1的个数集中在某个小范围,说明随机数质量有问题。

4.4 知识体系总览

下面这张图,把密钥生成的核心逻辑串起来了。你可以看到,从参数固化到随机数生成,再到密钥对计算和校验,每一步都环环相扣。

SM2密钥生成知识体系 椭圆曲线参数选择 素数域 p 曲线系数 a, b 基点 G 基点阶 n 密钥对生成算法 生成私钥 d ∈ [1, n-2] 计算公钥 P = d * G 校验 P 在曲线上 随机数质量对密钥安全的影响 硬件TRNG PRNG + 熵源混合 软件随机数(慎用) 随机性测试 TEE内参数必须固化

4.5 避坑指南:我踩过的三个雷

最后,分享几个实战中容易翻车的地方:

  • 雷区一:随机数种子复用。我曾经在调试阶段为了复现问题,固定了随机数种子。结果上线前忘了改回来——所有设备生成的私钥一模一样。嗯,那次被骂得不轻。
  • 雷区二:公钥未校验。生成公钥后,一定要检查它是否在曲线上。攻击者可能通过注入无效曲线点,诱导你泄露私钥信息。
  • 雷区三:私钥暴露在TEE边界。私钥生成后,只能在TEE内部使用。我见过有人为了方便,把私钥通过共享内存传出去——那TEE的保护就形同虚设了。

一句话总结:SM2密钥生成,参数选对是基础,算法实现要严谨,随机数质量是底线。这三条缺一条,密钥安全就是空话。