密钥生成审计:生成过程日志、随机数检测、合规性检查
密钥生成是整个SM2生命周期里最容易被忽视的一环。很多人觉得“生成密钥嘛,调个库就完事了”。但我在几次项目中踩过坑后才发现——生成那一刻没审好,后面一切审计都是空中楼阁。这一章咱们就聊聊密钥生成阶段的三项硬核审计点:日志记录、随机数质量、合规性检查。
1. 生成过程日志 —— 审计的“黑匣子”
为什么非要把日志单独拎出来?因为密钥生成是不可逆操作,一旦过程有纰漏,你没法让时光倒流。日志就是唯一的还原现场工具。我个人习惯要求日志必须包含以下关键字段:
| 字段 | 说明 | 示例 |
|---|---|---|
| 时间戳 | 高精度UTC时间,含毫秒 | 2025-04-07T08:32:17.823Z |
| 操作标识 | 生成操作用UUID唯一标记 | gen-uuid-a1b2c3... |
| 密钥标识 | 生成的密钥公钥/ID | SM2-key-20250407-001 |
| 随机数源 | 硬件/软件RNG,熵池哈希值 | hw-rng: sha256(entropy)=... |
| 随机数检测结果 | 检测项、统计量、P-value | 频数检测: P=0.43 通过 |
| 操作者/系统 | 调用方身份或服务名称 | kms-srv-03@internal |
| 审计签名 | 整个日志记录的HMAC | hmac_sha256(k, log_data) |
这里有个细节:日志必须是写前日志(Write-Ahead Log),而不是事后补录。我见过有些系统先生成密钥再写日志,结果生成过程中断电,日志丢了,密钥却已经写入了存储——这就没法审计了。逻辑应该是:先落日志,再执行生成,生成成功更新日志状态为完成。
2. 随机数检测 —— 别信“随机”是随机的
SM2密钥的随机数质量直接影响安全性。你以为操作系统自带的 /dev/random 就够用了?实际上很多嵌入式环境或容器环境下的熵池可能严重不足。我参与过的一个IoT项目,就是因为随机数源用的默认软件RNG,生成的密钥对居然有重复——概率极低,但确实发生了。从那以后,我对随机数检测有了执念。
国密标准GM/T 0005-2021《随机性检测规范》规定了15项检测,但审计时通常只要求覆盖以下核心项:
- 频数检测(Monobit Test)—— 看0和1的比例是否接近 1:1
- 游程检测(Runs Test)—— 检查连续相同比特的长度分布
- 块内频数检测(Block Frequency Test)—— 分块看比例
- 近似熵检测(Approximate Entropy)—— 检测重复模式的复杂度
- 累加和检测(Cumulative Sums)—— 检测正向/反向偏移
一般做法是:取至少1Mbit的随机数样本,调用检测工具(如国密推荐的 GRND_Tester 或开源工具 dieharder),每个检测项输出P-value。只有当P-value ≥ 0.01时才算通过。审计时需检查原始检测报告,不能只看“通过”二字——要确认样本量、检测参数是否合规。
代码示例(伪代码,实际调用需根据具体库调整):
# 从HWRNG读取1Mbit随机数
random_bits = hw_rng.read_bits(1024 * 1024)
# 调用国密检测工具
for test in [monobit, runs, block_freq, approx_entropy, cumsum]:
result = gm_random_tester(test, random_bits)
audit_log.append(f"{test.name}: P-value={result.p_value}")
if result.p_value < 0.01:
raise AuditFailure(f"随机数检测失败: {test.name}")
3. 合规性检查 —— 对着一纸清单打勾
合规性检查说白了就是对着标准一条条核对。我建议把检查项做成表格,每次生成密钥后自动生成检查报告。以下是SM2密钥生成审计的典型检查清单:
| 检查项 | 依据标准 | 通过条件 |
|---|---|---|
| 随机数源认证 | GM/T 0012-2020 | 硬件RNG通过FIPS140-2 Level 2或经国密认证 |
| 密钥长度 | GB/T 32918.1-2016 | SM2密钥长度256位 |
| 密钥参数验证 | GB/T 32918.1-2016 | 基点G、阶n、余因子h正确 |
| 随机数通过检测 | GM/T 0005-2021 | P-value ≥ 0.01 且样本量≥1Mbit |
| 日志完整性 | 内部审计策略 | 日志已签名,且写入在生成前 |
| 密钥生成环境 | 等保2.0三级 | 在物理隔离环境中执行,无网络暴露 |
每一条检查都应当有证据:比如硬件RNG的认证证书扫描件、检测报告PDF、日志记录哈希等。没有证据的检查等于没做——这是我被审计老师傅怼过后才明白的。
4. 避坑指南:我踩过的三个坑
- 坑一:随机数检测过了,但密钥对仍然弱。 我曾经遇到一个情况:随机数序列本身质量没问题,但密钥生成算法(SM2点乘)实现有bug,导致部分私钥落在小阶子群。后来我们增加了密钥参数验证(检查私钥是否小于群阶n,公钥是否在曲线上),这才堵住漏洞。
- 坑二:日志签名用的密钥和业务密钥混用。 嗯,这是典型的设计问题。日志签名密钥一旦泄露,攻击者就可以伪造任意日志。必须单独派生一个审计签名密钥,并且与业务密钥隔离存储。
- 坑三:只看单次检测P-value,不看趋势。 每次生成都检测,P-value忽高忽低属正常。但如果你把100次检测的P-value画成直方图,发现它们严重偏离均匀分布——那就说明随机数源有问题,即使每次都能通过阈值。所以审计报告里最好附带P-value分布图(当然,手动审查时可只看统计摘要)。
上面这个流程图把密钥生成审计分成了两个域:左侧是生成与检测,右侧是合规与记录。注意第6步“生成过程日志”必须放在随机数检测和密钥生成之后、签名归档之前,并且采用WAL策略。我记得有一次合规审查,对方要求展示整个过程的时间轴——有了这个流程和对应的日志,几分钟就讲清楚了。