2、密钥生成与分发追溯
密钥这东西,说白了就是安全体系的命根子。你审计的时候,如果连密钥怎么生出来的、怎么发出去的都说不清楚,那后面的追溯全是空谈。我个人习惯,拿到一个系统的密钥管理方案,先看两件事:生成策略够不够随机,分发协议有没有防篡改。
2.1 密钥生成策略
密钥生成不是随便敲几个随机数就完事的。我见过不少项目,开发图省事,直接用 rand() 或者 Math.random() 来生成密钥。嗯,这种密钥在审计面前基本等于裸奔。
正确的做法,必须使用密码学安全的随机数生成器(CSPRNG)。比如 Linux 下的 /dev/urandom,或者 OpenSSL 的 RAND_bytes()。审计时要重点检查:
- 随机源:是否依赖硬件熵源?有没有 fallback 到弱随机?
- 生成算法:是直接用随机数,还是经过 KDF(密钥派生函数)处理?
- 密钥长度:对称密钥至少 256 位,RSA 至少 2048 位,ECC 至少 256 位。
- 生命周期:密钥有没有过期时间?过期后怎么轮换?
| 密钥类型 | 推荐算法 | 最小长度 | 生成方式 |
|---|---|---|---|
| 对称密钥 | AES-256 | 256 bit | CSPRNG 直接生成 |
| 非对称密钥 | RSA / ECDSA | 2048 bit / 256 bit | 专用密钥生成算法 |
| 会话密钥 | DH / ECDH | 256 bit | 密钥协商协议 |
| 派生密钥 | HKDF / PBKDF2 | 取决于主密钥 | KDF 从主密钥派生 |
2.2 安全分发协议
密钥生成好了,怎么安全地送到对方手里?这是另一个大坑。直接通过网络传输明文密钥?那跟把密码写在明信片上没区别。
实际生产环境里,最常用的就是 Diffie-Hellman 密钥交换协议。它的核心思想是:双方在不安全的信道上,通过数学计算协商出一个共享密钥,即使中间人偷听了所有通信,也算不出这个密钥。
我简单说一下 DH 的流程,你审计的时候要对照着看:
- 参数协商:双方约定一个大素数 p 和生成元 g。
- 生成私钥:各自生成一个随机数作为私钥(a 和 b)。
- 计算公钥:A = g^a mod p,B = g^b mod p。
- 交换公钥:把 A 和 B 发给对方。
- 计算共享密钥:A 方计算 B^a mod p,B 方计算 A^b mod p,结果相同。
但是,DH 有一个致命弱点:中间人攻击。攻击者可以冒充双方,各自建立两个 DH 会话。你想想看,如果 A 和 B 没有验证对方的身份,那密钥其实是被攻击者控制的。
解决办法?用 认证的密钥交换协议。比如:
- STS 协议:在 DH 交换过程中加入数字签名,验证双方身份。
- ECDHE + 证书:TLS 1.3 的做法,用椭圆曲线 DH 临时密钥,配合 X.509 证书做身份认证。
- 预共享密钥(PSK):双方事先有一个共享密钥,用它来加密 DH 参数。
2.3 日志记录要点
密钥生成和分发的日志,是审计追溯的核心证据。但很多系统的日志,要么记不全,要么记了也没用。我总结了几条必须记录的要点:
| 阶段 | 必须记录的字段 | 说明 |
|---|---|---|
| 密钥生成 | 时间戳、密钥ID、算法、长度、随机源类型、熵池状态、操作人/模块 | 记录随机源是为了后续审计随机性质量 |
| 密钥分发 | 时间戳、源身份、目标身份、协议类型、参数哈希、是否使用证书 | 参数哈希用于验证协议是否被篡改 |
| 密钥接收 | 时间戳、接收方身份、密钥指纹、验证结果 | 密钥指纹用于确认收到的密钥与发送的一致 |
| 密钥激活 | 时间戳、密钥ID、生效时间、失效时间、使用范围 | 明确密钥的生命周期状态 |
另外,日志本身也要防篡改。建议使用 区块链式日志结构,每条日志包含前一条的哈希值。或者至少用 HMAC 对日志条目做完整性校验。否则攻击者删改日志,你根本发现不了。
嗯,这里还要注意一个细节:日志里绝对不能记录密钥本身。只记录密钥的哈希值或指纹。密钥明文一旦落入日志,那整个安全体系就崩了。
最后说一句,密钥追溯不是事后诸葛亮。你得在设计阶段就把日志埋好,把事件ID串好。等出了安全事件再回头补日志,那已经来不及了。我每次做审计,第一件事就是看密钥日志的完整性——如果日志本身都不可信,那整个审计报告就是废纸。