3. SM2密钥对生成与工程管理
SM2 的密钥对生成看起来只有两步:取一个随机数 d,再算一个点 P = [d]G。但在工程实践中,真正决定系统安全性的往往不是这两步数学运算,而是随机数质量、编码格式、存储方式和生命周期管理。本节围绕这四个环节展开,重点说明“怎么做”和“怎么判断做对了”。
私钥随机数:范围、来源与常见错误
SM2 推荐曲线参数中,基点 G 的阶 n 是一个 256 位素数。私钥 d 必须满足 1 ≤ d ≤ n-2,即它是一个位于 [1, n-2] 区间内的整数。这个范围不是可选项:d = 0 会使公钥退化为无穷远点,d = n 或 d = n-1 在部分实现中会引发边界问题,因此标准明确排除了这些取值。
随机数来源必须使用密码学安全的伪随机数生成器(CSPRNG),例如操作系统提供的 /dev/urandom、getrandom()、BCryptGenRandom 或硬件随机数发生器。工程中最常见的错误有三类:一是用普通语言库的 rand() 或时间戳作为种子,这类随机数可预测;二是随机数生成后未做范围检查,直接当作私钥使用;三是把随机数生成和私钥派生混在一起,导致同一随机数被复用。一个稳妥的做法是:生成 32 字节随机数,将其解释为大端整数,若不在 [1, n-2] 内则重新生成,直到满足条件。
公钥计算:从私钥到曲线点
公钥是曲线上的一个点 P = (x, y),由 P = [d]G 计算得到。这里的 [d]G 表示基点 G 的 d 倍点,使用椭圆曲线点乘运算。工程实现中通常调用密码库的标量乘法接口,例如在 OpenSSL 中通过 EC_POINT_mul 完成,在 GmSSL 或 BouncyCastle 中也有对应封装。需要强调的是,点乘运算本身必须使用常数时间实现,避免通过时间侧信道泄露私钥信息。
计算完成后,公钥点需要序列化。SM2 公钥有两种常见编码:未压缩格式和压缩格式。未压缩格式为 04 || x || y,共 65 字节;压缩格式为 02/03 || x,共 33 字节,其中 02 表示 y 为偶数,03 表示 y 为奇数。压缩格式能减少传输和存储开销,但需要接收方支持解压。工程中若与外部系统交互,应优先确认对方支持的编码格式,避免因格式不一致导致验签失败。
密钥编码格式:私钥、公钥与容器
私钥的编码同样需要规范。裸私钥是 32 字节大端整数,但直接存储裸私钥不利于识别和导入。常见做法是使用 ASN.1 DER 编码的 ECPrivateKey 结构,或使用 PKCS#8 格式封装。公钥则常使用 SubjectPublicKeyInfo 结构。若需要跨系统交换,还可以使用 PEM 文本格式,即以 -----BEGIN EC PRIVATE KEY----- 或 -----BEGIN PUBLIC KEY----- 包裹 Base64 内容。
下表给出几种常见格式的对比,便于在工程中按场景选择:
| 对象 | 格式 | 典型长度 | 适用场景 |
|---|---|---|---|
| 私钥 | 裸 32 字节 | 32 B | 内部二进制存储、HSM 导入 |
| 私钥 | PKCS#8 DER | 约 100–150 B | 跨库导入、密钥容器 |
| 公钥 | 未压缩点 | 65 B | 通用交换、验签 |
| 公钥 | 压缩点 | 33 B | 带宽受限、区块链地址 |
| 公钥 | SubjectPublicKeyInfo | 约 90 B | 证书、TLS 配置 |
密钥存储与生命周期管理
私钥存储的核心原则是“最小暴露面”。软件实现中,私钥应加密保存,例如使用口令派生密钥(PBKDF2、scrypt 或 Argon2)加密后再落盘;更高安全等级应使用 HSM、智能卡或 TEE,使私钥永不离开安全边界。公钥可以公开存储,但仍需保证完整性,防止被替换。
生命周期管理包括生成、使用、轮换、归档和销毁五个阶段。生成阶段要记录密钥用途、算法、曲线和生成时间;使用阶段要限制调用权限和调用频率;轮换阶段应设定有效期,例如签名密钥一年一换,加密密钥按数据敏感级别决定;归档阶段要保证旧密钥可验证历史签名;销毁阶段要确保私钥被安全擦除,而不是简单删除文件。工程中建议为每个密钥分配唯一标识 keyId,并在签名或密文中携带该标识,便于后续定位和轮换。
在实际工程中,建议把上述流程固化为密钥管理策略:生成时强制使用 CSPRNG 并做范围校验;编码时明确格式并写入文档;存储时区分软件加密与硬件保护;生命周期上为每个密钥建立台账,记录 keyId、用途、算法、生成时间、有效期和状态。这样,当需要轮换或排查问题时,才能快速定位到具体密钥,而不是在一堆无标识的文件中猜测。
[1, n-2] 范围?公钥编码是否与对端一致?私钥是否加密或由 HSM 保护?是否分配了唯一 keyId?是否设定了有效期和轮换计划?销毁时是否执行了安全擦除?