内核把设备噪声转成密钥
Linux 应用通常从内核的密码学安全生成器取得随机字节,不是每输出一位,就必须重新采集一位物理噪声。不过,初始化和状态复用仍然重要。机器繁忙不自动意味着安全,机器安静也不自动意味着故障。判断之前,应确认所用接口、内核版本,以及启动或克隆流程,不能只凭一个计数器就宣布密钥已经不安全。 区分采集与输出 Linux 6.12 的实现把输入混入基于 BLAKE2s 的池,并用 ChaCha20 生成输出。这是该版本的实现细节,不是所有未来版本永远不变的接口契约。硬件来源、中断时序和引导程序输入,按具体平台的信任规则参与。加入字节与把这些字节计入初始化熵估算,是两件不同的事;内核不能假设用户任意提供的一串字节都包含新鲜、不可预测的信息。 在这个实现中,poolsize 与初始化完成后的熵计数都达到二百五十六位,读取不会像消耗燃料一样扣减计数。因此,旧手册里四千零九十六位的描述,不应直接变成所有机器的告警阈值。应记录运行内核并检查对应行为,不能声称所有 Linux 版本的计数都一样,也不能仅因数字较小就判定随机输出薄弱。 选择会等待初始化的接口 默认 getrandom 会等到初始化完成。带 GRND_NONBLOCK 时,尚未初始化会报告 EAGAIN,使应用能够说明状态而不无限等待。初始化以后,默认源的一次请求若不超过二百五十六字节,具有文档规定的完整读取与信号保证;调用方仍应检查错误和返回长度。更大请求要正常处理部分返回和中断,不能把小请求的保证扩大到所有缓冲区。 random 设备从 Linux 5.6 起改变了行为:初始化后不再因为所谓熵耗尽而阻塞。在核对的 Linux 6.12 源码中,GRND_RANDOM 也不选择一个独立、会被耗尽的输出池。有些手册仍保留旧行为描述,不应把历史限制与当前内核结论混合。直接读取 urandom 可能发生在初始化之前;早期启动生成密钥,应使用支持初始化等待的接口。 坏掉的样子 早期启动仍可能缺少足够的可信计入输入。容器中缺少设备节点则是另一类接口问题:getrandom 不需要设备路径,普通容器共享宿主内核。操作等待时,应有明确的启动失败或等待策略,而不是改用时间戳、可预测种子或不安全的备用输出。让服务尽快启动,不是降低密钥生成要求的理由。 保存的种子可以帮助下一次启动,但把文件写回 urandom 并不会自动增加熵计数。一个三十二字节文件,或者某种硬件设备的存在,都不能单独保证立即就绪。应使用发行版提供的种子管理机制,了解它何时、依据什么信任条件计入熵。保护种子文件,避免在克隆镜像里分发相同的保存种子,并让引导程序专用的种子处理与操作系统流程一致。 复制磁盘镜像和恢复运行中的虚拟机,是两种不同风险。前者可能复制种子文件或已经生成的主机密钥,后者可能复制正在使用的生成器内存状态。新输入及虚拟机生成标识处理,可以让后续状态分离。未来输出完全相同是需要调查的风险,不是每次克隆必然出现的结果;两台机器使用同一份种子,也不足以证明它们全部生成器状态完全一致。 输入计入、初始化与输出各有边界。仅标明的 Linux 6.18.44 结果属于保留历史观察;本轮没有请求随机字节。 快速验证 在 Linux 上运行下面的 Python 3 脚本。它读取计数器,并请求一次非阻塞的三十二字节输出;不会打印随机内容,不读取私钥,不更改种子文件,也不需要管理员权限。这样可以观察接口是否就绪,而不把诊断过程变成密钥材料收集或系统配置变更。 ...