第4章 密钥存储与保护机制
4.1 硬件安全存储:把钥匙锁进保险柜
密钥安全的第一道防线,就是物理存储位置。你想想看,软件里存的密钥,攻击者拿到内存dump就能读出来。这显然不行。
硬件安全存储说白了,就是把密钥放到一个攻击者“摸不到”的地方。HSM里最常用的手段,是专用安全NVM和一次性可编程存储。
- 安全NVM(Non-Volatile Memory):集成在HSM芯片内部的Flash或EEPROM。外部总线访问不到,只有内部安全逻辑能读写。我在项目中遇到过一件事——某次渗透测试,攻击者试图通过JTAG读出NVM内容,结果发现安全位熔断后JTAG直接被禁用。嗯,不是所有芯片都这么良心,有的厂商忘了熔断安全位,导致批量泄露。
- OTP(One-Time Programmable):密钥注入后一次性写入,之后只能读不能改。这玩意儿的物理机制是熔断式或击穿式存储单元。一旦写入,物理上就无法擦除。
- SRAM PUF:利用芯片上电时SRAM单元的随机物理偏差生成密钥。密钥不存在于任何存储介质中,只在需要时“现造”出来。断电后密钥消失——这叫“零存储”方案。
我的选型建议:对于量产HSM,我习惯将根密钥(Root Key)存入OTP,派生会话密钥使用临时SRAM。这样既保证永久性,又兼顾灵活性。
4.2 密钥加密存储:即使偷走也读不懂
有时候硬件存储空间不够,必须把密钥放到外部Flash。这时候怎么办?
加密!用HSM内部的硬件密钥引擎对导出密钥进行加密保护。攻击者拿到外部存储的密文,没有内部的加密密钥也无法还原明文。
4.2.1 密钥层次结构
实际我见过的大多数商用HSM,都采用多级密钥体系:
| 层级 | 名称 | 存储位置 | 保护方式 |
|---|---|---|---|
| Level 1 | 主密钥(MK) | HSM内部OTP/安全NVM | 物理隔离+防篡改 |
| Level 2 | 密钥加密密钥(KEK) | HSM内部SRAM | 由MK解密后暂存 |
| Level 3 | 工作密钥(WK) | 外部Flash/本地存储 | 使用KEK的AES加密保护 |
你看,即使外部Flash被偷走,攻击者得到的是AES-256密文。没有MK和KEK,破解基本没戏。这事儿我吃过亏——早期设计时我把KEK存进了共享SRAM区域,结果侧信道攻击直接把KEK给撸了出来。后来改成了硬件专用寄存器,才算彻底堵住漏洞。
4.2.2 算法选择与认证加密
单纯加密不够,得防篡改。我建议使用AEAD(认证加密)模式,比如AES-GCM。既保密又完整性校验,一条指令搞定。
我个人的代码习惯是这样:
// 伪代码:HSM内部使用AES-GCM包装密钥
void wrap_key(uint8_t *plain_key, uint8_t *wrapped_key) {
// 从内部安全寄存器加载KEK
uint8_t kek[32];
hsm_read_secure_register(KEK_SLOT, kek);
// 生成随机IV
uint8_t iv[12];
hsm_trng_generate(iv, 12);
// AES-GCM加密
aes_gcm_encrypt(plain_key, 16, kek, iv, wrapped_key, tag);
// 输出格式:IV + Ciphertext + Tag
memcpy(wrapped_key, iv, 12);
memcpy(wrapped_key+12, ciphertext, 16);
memcpy(wrapped_key+28, tag, 16);
}
我曾经踩过的坑:有一次用了AES-CBC,没加HMAC。结果攻击者通过密文块重放,把密钥恢复成了全零⋯⋯从那以后,我再也不用CBC单独加密密钥了,必须配合MAC或者直接上GCM。
4.3 防篡改封装:物理攻防的博弈
密钥存好了,也加密了。但攻击者会直接拆芯片。研磨、FIB、激光切割,啥手段都有。
防篡改封装就是对这类物理攻击的“硬刚”。
4.3.1 主动屏蔽层
芯片顶层走线布满随机蛇形网络。一旦被钻孔或磨片,线路断开或短路,内部传感器立刻触发——密钥抹除。
我有一回调试样片,不小心碰到了带屏蔽层的区域,结果整个HSM自毁,返工了一周。嗯,这玩意儿灵敏度极高,大家焊接测试时一定戴防静电腕带,别问我怎么知道的。
4.3.2 抗探测涂层
现代HSM还会涂一层专用防护涂层。这种涂层用机械方式去除时,会破坏下面的金属层。化学方式去除呢?涂层中含有特殊化合物,遇到特定溶剂会变色或释放气体——检测电路同样会触发自毁。
| 防护类型 | 原理 | 触发条件 |
|---|---|---|
| 主动屏蔽层 | 蛇形走线网络 | 线路断裂/短路 |
| 防护涂层 | 机械/化学敏感材料 | 剥落、腐蚀、变色 |
| 光感应器 | 集成光敏二极管 | 封装被打开、光照进入 |
| 温度/电压传感器 | 实时监控环境参数 | 超温、欠压、过压 |
4.3.3 封装完整性验证
除了物理防护,还要有逻辑验证。HSM上电时会校验封装状态。如果发现屏蔽层阻抗异常,或者涂层电容值不对——直接锁死,不再提供任何密码服务。
我建议这么实现:
// 上电自检中验证防篡改封装
int tamper_self_test() {
// 测量屏蔽层环路阻抗
uint32_t shield_impedance = measure_shield_impedance();
if (abs(shield_impedance - EXPECTED_IMPEDANCE) > TOLERANCE) {
return TAMPER_DETECTED;
}
// 校验涂层电容
uint32_t coating_cap = measure_coating_capacitance();
if (abs(coating_cap - EXPECTED_CAPACITANCE) > TOLERANCE) {
return TAMPER_DETECTED;
}
// 清除密钥存储
if (TAMPER_DETECTED) {
secure_erase_all_keys();
return HSM_FOREVER_LOCKED;
}
return SELF_TEST_PASS;
}
核心观点:三个环节必须联动——硬件安全存储提供基础隔离,密钥加密存储提供算法级保护,防篡改封装提供物理层保障。缺一不可。
4.4 本章知识结构图
我把这三层保护机制的关系整理了一下,画了张图,帮你快速建立整体认知:
4.5 避坑总结
- 不要迷信单一保护:光靠硬件存储不行,加密密钥有泄露风险;光靠加密证明软件加固不够,物理攻击直接绕开。三样都得用。
- 防篡改不是摆设:很多人以为屏蔽层只是“高级装饰”,结果某大厂的产品被用紫外灯照开封装,直接读出了OTP位。嗯,光传感器没加。
- 密钥生命周期管理:存储只是开始。密钥怎么注入、怎么轮换、怎么销毁,都得纳入设计。我个人习惯在设计阶段就把这些流程画成状态机,避免后期补丁打到飞起。