3、SM2密钥体系:公私钥对生成原理、密钥存储安全规范、密钥生命周期管理
聊到SM2固件保护,密钥体系是绕不开的核心。说白了,你整个安全方案的强度,最终都取决于密钥本身是否可靠。我见过不少项目,算法选得挺先进,加密流程也跑得通,结果密钥管理一塌糊涂——硬编码在固件里、存储权限全开、生命周期没人管。嗯,这种方案基本等于没穿衣服出门。
这一章我们就来把SM2的密钥体系彻底讲透。从数学原理到存储规范,再到全生命周期的管理策略,我会把我在实际项目中踩过的坑和总结的经验都放进来。
3.1 公私钥对生成原理
SM2是基于椭圆曲线密码学的。你想想看,它为什么比RSA更受嵌入式系统欢迎?因为同样的安全强度下,SM2的密钥长度更短,计算量更小。对于资源受限的MCU和安全芯片来说,这简直是天赐良机。
公私钥对的生成,核心就三步:
- 选取椭圆曲线参数:SM2使用国家密码管理局定义的256位素域椭圆曲线。参数是固定的,包括素数p、系数a和b、基点G、阶n等。这些参数你不需要自己算,直接用标准库就行。
- 生成私钥:随机选择一个小于n的大整数dA。这个dA就是私钥。注意,随机数质量至关重要。我曾经在项目里遇到过因为硬件随机数发生器故障,导致多个设备生成了相同的私钥——那场面,简直是灾难。
- 计算公钥:通过标量乘法计算PA = dA * G。G是基点,dA是私钥,PA就是公钥。这个计算是单向的,从私钥算公钥很容易,反过来几乎不可能。这就是椭圆曲线密码学的安全基石。
核心要点:SM2私钥本质上是一个256位的随机数,公钥是椭圆曲线上的一个点(包含x和y坐标,共512位)。生成过程必须确保随机源的熵足够高,否则整个密码体系形同虚设。
我习惯在固件开发阶段,专门写一个测试用例来验证随机数发生器的质量。跑个几万次,检查是否有重复值出现。这个习惯帮我提前发现了两次硬件缺陷。
3.2 密钥存储安全规范
密钥生成出来之后,放哪儿?这是个大问题。很多开发者图省事,直接把私钥以明文形式存在Flash里。我告诉你,这等于把家门钥匙挂在门外。
安全存储的核心原则就一条:私钥永远不应该以明文形式出现在非安全存储区。
具体来说,我建议遵循以下规范:
| 存储位置 | 安全等级 | 适用场景 | 注意事项 |
|---|---|---|---|
| 安全芯片(SE) | 最高 | 支付、身份认证等高安全场景 | 成本较高,需额外采购 |
| 硬件安全模块(HSM) | 高 | 密钥生成、证书签发等后端服务 | 通常用于产线或服务器端 |
| MCU内部OTP/eFuse | 中高 | 固件签名密钥、设备唯一密钥 | 一次性写入,不可更改 |
| 加密后存储在Flash | 中 | 固件升级密钥、会话密钥 | 需要额外的密钥加密密钥(KEK)保护 |
| 明文存储在Flash | 极低 | 绝对禁止 | 任何场景都不应该这样做 |
避坑指南:我曾经接手过一个项目,前任工程师把SM2私钥直接定义成一个const数组放在代码里。更离谱的是,这个数组还被编译进了固件镜像的只读段。攻击者只要用binwalk扫一下固件,就能把私钥提取出来。这种方案,连最基础的防护都谈不上。
对于大多数嵌入式固件保护场景,我推荐的做法是:
- 产线预置:在产线阶段,通过安全环境生成密钥对,将私钥直接写入MCU的OTP区域或安全芯片。公钥可以公开,用于固件签名验证。
- 派生密钥:如果设备需要多个密钥,可以从根密钥通过KDF(密钥派生函数)派生。这样只需要安全存储一个根密钥即可。
- 密钥封装:对于需要存储在Flash中的密钥,使用SM4等对称算法加密后再存储。加密密钥来自安全芯片或OTP。
3.3 密钥生命周期管理
密钥不是永久的。它和人一样,有出生、有使用、有退役。我见过很多团队只关注密钥生成和存储,却忽略了生命周期管理,结果密钥泄露了都不知道该换。
一个完整的密钥生命周期包括以下阶段:
- 生成阶段:在安全环境中生成,确保随机数质量。产线阶段尤其要注意,我建议使用HSM或安全芯片来执行生成操作,而不是让MCU自己生成。
- 分发阶段:将密钥安全地部署到目标设备。对于固件保护场景,私钥通常不离开安全芯片。公钥可以随固件一起分发。
- 使用阶段:密钥在设备中执行签名、解密等操作。这个阶段要监控密钥的使用次数和异常行为。比如,如果某个私钥在短时间内被频繁调用,可能是攻击者在尝试暴力破解。
- 轮换阶段:定期更换密钥。SM2密钥的推荐轮换周期取决于安全等级,一般建议1-2年。对于高安全场景,可以缩短到半年。
- 撤销阶段:当密钥泄露或设备退役时,需要撤销密钥。对于固件签名密钥,可以通过CRL(证书撤销列表)或OCSP(在线证书状态协议)来实现。
- 销毁阶段:彻底删除密钥。对于存储在安全芯片中的密钥,通常有专门的销毁指令。对于OTP区域,销毁意味着物理破坏芯片。
个人经验:我习惯在固件中实现一个密钥版本号机制。每次轮换密钥时,版本号递增。这样即使旧密钥泄露,新固件也会使用新密钥签名,旧密钥签名的固件会被拒绝升级。这个机制实现起来很简单,但效果非常好。
下面这张图展示了SM2密钥从生成到销毁的完整生命周期流程:
在实际项目中,我建议你为每个密钥建立一个生命周期档案。记录它的生成时间、使用次数、轮换历史、撤销原因等。这样当安全事件发生时,你能快速定位问题。
最后说一句:密钥管理没有银弹。安全等级越高,成本越高,操作越复杂。你需要根据产品的实际威胁模型来权衡。但有一条底线——私钥绝对不能明文存储在可读的存储介质中。这条底线,无论如何都不能碰。