密钥生成策略:从熵源到算法选择
密钥生成,是整个密钥生命周期里最基础也最容易出问题的一环。我见过不少项目,加密算法选得很强,密钥长度也够,结果一查——密钥是用 rand() 生成的。嗯,那基本等于没锁门。
这一节我们重点聊两件事:真随机数生成器(TRNG)和伪随机数生成器(PRNG)到底差在哪,以及在实际工程里怎么选、怎么用。
TRNG vs PRNG:核心差异
先给个直观对比。你想想看,TRNG 是从物理世界「采集」随机性,比如热噪声、量子效应、放射性衰变。PRNG 则是用算法「模拟」随机性,给它一个种子,它就能源源不断地吐出看起来随机的数。
| 特性 | TRNG | PRNG |
|---|---|---|
| 熵来源 | 物理过程(热噪声、时钟抖动等) | 算法 + 种子 |
| 输出是否可预测 | 不可预测(理论上) | 种子已知则可预测 |
| 输出速率 | 慢(通常几十 Kbps ~ 几 Mbps) | 快(可达 Gbps 级别) |
| 硬件依赖 | 需要专用硬件 | 纯软件即可 |
| 典型用途 | 生成种子、密钥材料 | 派生密钥、IV、nonce |
说白了,TRNG 是「真随机」,但慢且贵;PRNG 是「假随机」,但快且便宜。实际工程里,两者是配合使用的,不是二选一。
TRNG:物理熵源的采集与挑战
TRNG 的核心是熵源。常见的物理熵源包括:
- 热噪声:电阻或二极管的热噪声,放大后采样
- 时钟抖动:两个独立振荡器之间的相位差
- 量子效应:光子到达时间、隧穿效应
- 放射性衰变:虽然可靠,但不太实用
我在一个 IoT 安全芯片项目里遇到过一个问题:芯片内部的 TRNG 模块在量产测试时,有大约 0.3% 的样本熵源输出偏了。后来排查发现,是晶圆工艺偏差导致热噪声放大器的增益不一致。嗯,硬件随机数生成器不是焊上去就能用的,必须做在线熵源健康检测。
PRNG:算法选择与安全等级
PRNG 分两类:密码学安全 PRNG(CSPRNG)和非密码学 PRNG。前者用于密钥生成,后者只适合模拟、测试等非安全场景。
常见的 CSPRNG 算法有:
- Hash_DRBG(基于哈希函数,如 SHA-256)
- HMAC_DRBG(基于 HMAC)
- CTR_DRBG(基于分组密码,如 AES-256-CTR)
- ChaCha20-based DRBG(流密码方案)
我个人习惯在服务端优先用 CTR_DRBG,因为它速度快,而且 AES 硬件加速指令(AES-NI)在主流 CPU 上都有。但在嵌入式环境里,如果芯片没有 AES 硬件,我会选 HMAC_DRBG,因为哈希函数通常有更小的代码体积。
/dev/urandom(Linux)、CryptGenRandom(Windows)、getrandom()(Rust)都是经过审计的 CSPRNG。除非你在做硬件安全模块(HSM)或嵌入式固件,否则直接用操作系统提供的接口就够了。
密钥生成的标准流程
一个安全的密钥生成流程,我建议至少包含以下步骤:
- 采集熵:从 TRNG 或系统熵池获取至少 256 位熵
- 熵提取:用哈希函数将熵压缩为固定长度的种子
- 种子注入:将种子安全地注入 CSPRNG
- 密钥派生:用 CSPRNG 生成所需长度的密钥材料
- 质量验证:对生成的密钥做统计测试(如 NIST SP 800-22)
我曾经在一个金融支付终端项目里,发现开发团队直接用 time(NULL) 做种子生成 RSA 密钥对。结果呢?同一秒内初始化的设备,生成的密钥完全一样。这个漏洞在安全审计时被标记为 Critical。从那以后,我对种子来源的检查就格外严格。
算法选择决策树
下面这张图是我在实际项目中总结的决策逻辑,你可以参考:
常见陷阱与避坑指南
这些年我踩过不少坑,挑几个典型的说说:
- 种子重用:同一个种子生成多个密钥,等于所有密钥都相关。我曾经在代码里发现有人把种子写死在配置文件里——嗯,那跟没用加密差不多。
- 忽略熵池枯竭:在容器或虚拟机里,系统熵池可能很小。启动时大量生成密钥,熵池被抽干,PRNG 会阻塞或降级。我建议在系统初始化时主动喂熵。
- TRNG 输出直接当密钥:TRNG 原始输出可能有偏,必须经过提取。NIST SP 800-90B 对熵源有明确的健康测试要求。
- 跨平台移植时忽略 PRNG 差异:Windows 的
CryptGenRandom和 Linux 的/dev/urandom行为不同。我在一个跨平台 SDK 里吃过这个亏,后来统一封装了一层。
标准与规范参考
如果你需要写安全规范或做合规审计,下面这几个标准是绕不开的:
- NIST SP 800-90A:CSPRNG 算法标准(Hash_DRBG、HMAC_DRBG、CTR_DRBG)
- NIST SP 800-90B:熵源健康测试与认证
- FIPS 140-3:密码模块安全要求,包含密钥生成
- BSI AIS 20/31:德国联邦信息安全局的随机数生成器评估标准
我个人习惯在项目初期就把这些标准列进需求文档里。别等到安全审计时才发现——那时候改起来成本就高了。