观察、决策、行动三个方框,旁边强调新的共享密钥仍需身份认证。

TLS ECDHE 保证前向保密

前向保密限制的是长期认证密钥日后泄露造成的影响。对于经过正确认证的临时 Diffie-Hellman 交换,攻击者仅取得长期认证私钥,不能据此恢复先前的会话机密。前提是临时机密没有一起被获取;它不会让已经被攻破的端点、导出的密钥日志或保存下来的明文突然变得安全。 两类密钥承担不同职责 ECDHE 中,双方分别生成临时私钥并交换公开份额。每一方把本地私钥与对方公开份额组合,得到相同的共享机密。旁观者虽然能看到公开份额,但在算法的安全假设成立时,缺少重现计算所需的私有值。新鲜的交换材料并不是双方在网络上公开商量出的一段秘密口令。 TLS 也不会把原始 ECDH 输出直接当成应用加密密钥。密钥调度还会派生不同的握手与应用流量机密,绑定握手上下文,并区分方向和用途。临时交换只提供其中一项关键材料,不能用“双方算出相同字节”替代整个传输协议,也不能略过后续派生和认证步骤。 证书按照信任规则把身份绑定到公钥,实际签署握手材料的是对应的私钥,不是证书这个数据对象自己在签名。TLS 1.3 的证书认证路径通过 CertificateVerify 认证握手记录。如果没有身份认证,主动中间人可以替换公开份额,分别和两端建立自己的共享机密;仅仅看到加密正常,并不能排除这种攻击。 RSA 或 Ed25519 认证密钥可以与临时交换并存,签名算法和密钥交换组是不同选择。TLS 1.3 还定义了仅使用 PSK 的恢复模式,后者不具备 DHE 带来的这项前向保密;PSK 配合 DHE 则会加入新的交换材料。可选 early data 的保证更弱,因此不能单凭 TLS 版本或证书算法标签,就推断所有阶段的流量都有相同保护。 坏掉的样子 长期重复使用同一个交换私钥,会削弱原本希望建立的泄露边界。随机数不足、临时私有值暴露、崩溃转储或 TLS 密钥日志,都可能泄露前向保密假设中不能被攻击者取得的材料。日后泄露流量机密,与日后泄露证书签名私钥,不是同一个威胁场景,不能混用结论。 会话进行时攻破端点,可能直接取得明文。长期认证私钥失窃后,能够拦截未来连接的攻击者也可能冒充服务器。前向保密保护的是特定的历史录制流量场景,并不会撤销泄露凭据,也不会修复仍在持续的入侵;这些问题仍需要独立的凭据轮换与事件处置。 机密销毁更是实现层面的问题,不能仅靠一句“用完就丢弃”来保证。把 Go 变量设为 nil,不证明内存、交换空间或诊断材料中的所有副本都已消失。应避免把机密写进日志,并把凭据失窃的处置与历史流量是否仍受保护的判断分开,不能用概念上的前向保密替代真实的数据暴露调查。 ...

十月 27, 2027 · 2 分钟 · XB Field Notes
内核依据设备噪声为加密安全随机数发生器供种。

内核把设备噪声转成密钥

即便一台很安静的服务器,在真正需要随机数之前也早就完成了播种,所以今天还会出问题的随机性事件几乎都不是「熵不够」,而是「状态被重放」:镜像里烤死的种子、被恢复的快照、回滚到上一次重播种之前的状态。内核并不朝你一滴一滴地滴熵;它把一点点设备噪声浓缩成一个生成器,然后无限地吐密钥流。 这个反转正是为什么围绕熵的大部分运维经验已经失效。盯着 entropy_avail、为取密钥去读 /dev/random、装一个补熵守护进程,这三件事针对的都是内核早已不再存在的稀缺;而真正会毁掉密钥的那件事——两台机器拿到同一个种子——在这些习惯里一个都看不出来。 熵池是输入,生成器是产物 内核把物理噪声混进来:中断时序抖动、设备延迟、平台自带的硬件随机数发生器,以及基于 CPU 的 jitterentropy;再用 BLAKE2s 把它们抽取进熵池。熵池给一组 ChaCha20 CRNG 播种,真正产出字节的是这些 CRNG。播种之后收集仍在继续,生成器也会被周期性重播种,但你已经吐出去的每一个字节,其强度由它出生时的那个状态决定,之后再发生什么都改不了。 一旦初始化完成,输出就是密钥流,而不是有限资源。entropy_avail 稳定在 256 位,也就是一个 ChaCha20 密钥的长度,而且你读它它也不会掉;读走 1 MiB 不消耗任何池内配额。random(4) 至今仍把 entropy_avail 描述成 0 到 4096 之间的取值、把 poolsize 描述成 Linux 2.6 之后固定 4096 位——正是这类文档让一条过期的告警一直活着。 /dev/random 不再是「更谨慎」的选择 从 Linux 5.6 起,/dev/random 在早期启动之外不再阻塞,其上的 O_NONBLOCK 也被忽略。那个独立的阻塞池已经消失,剩下的只是同一个生成器顶着历史名字。getrandom(2)(Linux 3.17 引入)默认从 urandom 源取数,只在那个源尚未初始化时阻塞;GRND_NONBLOCK 把这种阻塞变成 EAGAIN,GRND_RANDOM 则改为选择 random 源,也就是那个仍然可能无限期阻塞的源。 ...

十月 22, 2027 · 1 分钟 · XB Field Notes