第3章 SM4密钥结构分析
密钥结构这回事,说白了就是密钥在内存里怎么摆、怎么传、怎么展开。我刚开始做SM4集成时,以为只要把128位主密钥处理好就完事了。结果一上手,才发现轮密钥管理、密钥扩展状态、边界控制,哪个环节都可能出问题。嗯,这节课我们就来好好拆一拆——SM4的密钥到底长什么样,边界在哪里。
3.1 密钥的256位体系
你可能会问:SM4不是128位密钥吗?没错,主密钥是128位,但密钥结构实际操作的是一个256位的密钥树。它由两个128位的部分组成:主密钥和轮密钥扩展状态。主密钥是用户输入的原始种子,轮密钥扩展状态则是从主密钥派生出来的中间数据,用来生成32个32位的轮密钥。这两块合在一起,才是我们常说的完整密钥边界。
| 组件 | 位数 | 作用 |
|---|---|---|
| 主密钥 | 128 bit | 用户输入的原始密钥,是整个密钥树的根 |
| 轮密钥扩展状态 | 128 bit | 扩展过程中的中间变量,包含非线性变换结果 |
| 轮密钥(32个) | 32 × 32 bit | 每轮加密使用的子密钥,由扩展状态顺序生成 |
这里有个我特别想强调的点:轮密钥扩展状态虽然只存在于密钥扩展阶段,但如果攻击者能截获它,就可以直接逆向推导出主密钥。我个人习惯在扩展完成后,立即用专门的函数覆盖掉这个状态缓冲区,绝不让它在内存里多停留一秒。
3.2 密钥边界与生命周期
密钥边界,就是密钥从出生到销毁全程的管辖范围。我把它分成五个阶段,每个阶段都有明确的边界规则:
- 生成:必须在HSM或安全环境中产生,不能依赖标准库的伪随机。
- 分发:通过加密通道传输,不能明文传给其他模块。
- 使用:在进程内存中解密后使用,用完后立即擦除。
- 备份:使用密钥加密密钥(KEK)加密后存储,保证备份本身也是密文。
- 销毁:覆盖所有副本,包括内存、磁盘、日志文件、核心转储。
我以前遇到过一家公司的生产环境,密钥直接写在配置文件里,明文。结果打包时忘记剔除,随安装包一块儿发了出去。那个教训非常深刻。所以强烈建议在密钥边界管理中引入“最少副本”原则——密钥的副本数越少,安全风险越低。
3.3 密钥边界的典型场景
不同部署环境里,密钥边界的具体形态差别很大。下面这张表格总结了我在实际项目中见过的几种典型情况:
| 场景 | 密钥边界形式 | 主要风险点 |
|---|---|---|
| 嵌入式设备 | SoC片内OTP存储 + 内部SRAM | 调试接口未物理切断,可读OTP |
| 服务器软件 | 进程堆内存 + HSM | 核心转储泄露堆快照 |
| 移动App | 系统钥匙串 + SoC安全区域 | Root后钥匙串可被导出 |
| 云计算平台 | VSM/KMS + 加密实例 | 密钥缓存未及时回收 |
你发现没有?不同场景虽然技术栈不同,但矛盾是相同的:密钥在安全边界内停留的时间越短越好。我建议在设计密钥结构时,把主密钥和轮密钥扩展状态分开存放,并且使用硬件隔离手段,比如独立的内存区域或者专用安全芯片。
核心要点:SM4密钥结构由主密钥、轮密钥扩展状态和轮密钥三部分构成,整体形成256位的密钥树。实际开发中,边界管理的关键在于保护轮密钥扩展状态——它直接关联主密钥安全。我建议使用HSM或硬件隔离技术存储主密钥,并用专用的安全擦除函数清理所有临时缓冲区。