4、密钥体系设计:密钥分类与层级结构
聊到密钥体系,很多人第一反应就是「搞个 AES-256 就完事了」。嗯,真这么干过的人,后来都踩坑了。我早年参与过一个物联网项目,当时图省事,所有设备都用同一把密钥加密固件。结果一台设备被逆向,整个产品线都得召回。那次之后我才真正理解——密钥必须分层,而且每层的职责要划清楚。
说白了,密钥体系设计就是回答三个问题:谁保护谁?谁生成谁?谁销毁谁? 今天这一章,我们就从密钥分类和层级结构入手,把这件事彻底讲透。
4.1 为什么需要多层密钥?
你想想看,如果一把密钥既用来加密固件,又用来加密通信,还用来签名启动镜像——那它一旦泄露,整个系统就裸奔了。分层的目的很简单:把风险隔离在单层。
我习惯把密钥体系比作「保险柜 + 临时钥匙」的模型:
- 根密钥 是保险柜本身,极少动用,物理隔离
- 中间密钥 是保险柜里的主钥匙,定期更换
- 会话密钥 是每次开门的临时密码,用完即弃
这样做的好处很明显:即使会话密钥被截获,攻击者也拿不到中间密钥;即使中间密钥被破解,根密钥依然安全。每一层都是下一层的「保护者」。
4.2 密钥分类:三种核心角色
在启动校验场景中,我通常把密钥分为三类。它们各自的生命周期、存储位置和使用频率完全不同。
| 密钥类型 | 别名 | 存储位置 | 生命周期 | 典型用途 |
|---|---|---|---|---|
| 根密钥 | Root Key / KEK | eFuse / OTP / HSM | 设备全生命周期(不可更新) | 解密中间密钥、验证根证书 |
| 中间密钥 | Intermediate Key / KEK | 安全存储区(加密后存放) | 数月~数年(可轮换) | 解密会话密钥、签名次级镜像 |
| 会话密钥 | Session Key / SK | 内存(仅运行时存在) | 单次启动或单次通信(分钟级) | 加密通信、解密当前阶段数据 |
这里有个容易混淆的点:中间密钥不一定只有一层。我在做车规级芯片方案时,中间密钥就分了两级——一级用于固件解密,一级用于安全通信。层级越多,安全性越高,但性能开销也越大。一般嵌入式场景,三层就够了。
4.3 密钥层级结构:从根到叶
下面这张图是我自己项目里常用的三层密钥体系。你可以把它理解成「信任链」的骨架。
这个结构里,每一层都承担着「保护下一层」的职责。根密钥是信任锚点,它不直接参与业务加密,只用来解密中间密钥。中间密钥再解密会话密钥。会话密钥才是真正干活的那个。
4.4 各层密钥的生成与注入
密钥怎么来的?这个问题比你想的复杂。我见过不少团队在产线上直接用随机数生成根密钥,结果每台设备的根密钥都不一样,后续 OTA 升级时签名验证直接崩了。
正确的做法是:
- 根密钥: 在芯片出厂时由厂商注入,或者由设备制造商在安全环境中烧录。必须保证每台设备的根密钥唯一,但签名公钥可以相同(私钥保密)。
- 中间密钥: 由根密钥加密后存储在 Flash 中。可以在首次启动时由 BootROM 生成并加密写入,也可以在 OTA 时更新。
- 会话密钥: 每次启动时由中间密钥派生。不需要存储,用完就丢。
4.5 密钥轮换与销毁策略
密钥不是永久的。根密钥因为存储在 OTP 中,通常无法更新(除非芯片支持 OTP 覆写,但极少见)。中间密钥和会话密钥必须支持轮换。
| 密钥类型 | 轮换方式 | 销毁时机 | 注意事项 |
|---|---|---|---|
| 根密钥 | 不支持轮换(硬件绑定) | 设备报废时物理销毁 | 设计时必须考虑抗物理攻击 |
| 中间密钥 | OTA 更新时重新加密写入 | 新密钥生效后擦除旧密钥 | 必须保证旧密钥无法被回滚 |
| 会话密钥 | 每次启动自动生成 | 系统掉电或重启后自动消失 | 确保 RAM 清零,防止冷启动攻击 |
这里有个细节:中间密钥轮换时,必须用新密钥重新加密所有依赖它的数据。我习惯在密钥结构中引入「密钥版本号」,每次轮换版本号递增,旧版本的数据用旧密钥解密,新数据用新密钥。这样能平滑过渡。
4.6 实际项目中的层级设计示例
拿一个典型的 ARM Cortex-M 安全启动流程举例:
- 上电复位,BootROM 从 eFuse 读取根密钥
- BootROM 用根密钥 解密 Flash 中加密存储的中间密钥
- 中间密钥加载到安全 SRAM,BootROM 用中间密钥 验证 并解密第一级 Bootloader
- 第一级 Bootloader 用中间密钥 派生 出会话密钥,用于解密后续固件分区
- 会话密钥在每次启动时不同,防止重放攻击
你看,整个过程中,根密钥只出现了一次(步骤 2),中间密钥出现了两次(步骤 2、3),会话密钥只活在步骤 4 之后。每一层的暴露面都极小。
4.7 小结:设计密钥体系的三个检查点
每次设计完密钥体系,我都会问自己三个问题:
- 隔离性: 每一层密钥是否只做自己该做的事?根密钥有没有被软件直接调用?
- 最小暴露: 密钥在内存中存在的时间是否最短?用完有没有立即清零?
- 可轮换: 除了根密钥,其他密钥是否支持在线更新?轮换流程有没有引入回滚风险?
这三个问题能帮你筛掉 90% 的设计缺陷。剩下的 10%,嗯,那就要靠实际测试和攻防演练来发现了。