OpenWRT(9):随机数发生器urngd,以及/dev/random
urngd是一个基于时间jitter的非物理随机数发生器。urngd为Linux的/dev/random设备提供熵源,当/dev/random熵不足时,它会向其注入熵。
它会向其中注入熵。这确保了/dev/urandom也能从注入的熵中受益,尤其是在系统启动时,Linux的熵较低的情况下,urngd提供了足够的熵源
。
1 urngd:基于timer jitter的非物理RNG
1.1 urngd配置和启动
urngd配置:
Base system
urngd
package/system/urngd/files/urngd.init中定义了启动urngd的启动脚本:
#!/bin/sh /etc/rc.common
START=00
USE_PROCD=1
NAME=urngd
PROG=/sbin/urngd
start_service() {
procd_open_instance
procd_set_param command "$PROG"
procd_close_instance
}
reload_service() {
procd_send_signal $PROG
}
1.2 urngd流程
urngd主要功能是为 Linux 系统的随机数生成器提供高质量的熵源:
- urngd使用基于 CPU 时序抖动的算法来收集熵。
- 当系统的熵池熵值不足时,urngd 可以将收集到的熵注入到/dev/random设备。
- urngd 是一种非物理的随机数生成器,它依赖于软件算法来生成随机性。
- urngd 可以检测到系统熵池中的熵水平,并在熵水平较低时自动增加熵,从而避免/dev/random 阻塞读取操作。
- urngd 利用 OpenWrt 的 uloop 事件循环来处理熵的收集和注入。
main
uloop_init
urngd_init
jent_entropy_init--进行随机数生成器的初始化,包括健康测试(比如重复计数测试和自适应比例测试)和配置内部定时器(如果需要)。
jent_entropy_collector_alloc--为随机数生成器的实例分配内存,并配置过采样率和标志。
open--只写打开/dev/random设备。
uloop_fd_add--当有对/dev/random设备写ULOOP_WRITE时,调用回调函数。
low_entropy_cb
gather_entropy--收集新的熵,并将这些熵写入到/dev/random设备,从而提高系统的熵值。
jent_read_entropy
write_entropy
ioctl--文件描述符,指向/dev/random设备。RNDADDENTROPY
是ioctl调用的命令码,用于指示内核将额外的熵添加到熵池中。
gather_entropy
jent_read_entropy--从随机数生成器中读取随机数。如果检测到健康测试失败,将返回错误代码。
write_entropy
ioctl
uloop_run
uloop_done
urngd_done--在程序退出时清理和释放urngd服务使用的资源。
2 /dev/random
2.1 /dev/random
点击链接查看和 Kimi 智能助手的对话 https://kimi.moonshot.cn/share/cqud11bdf0j055dm7r7g
chr_dev_init
device_create--遍历devlist创建设备。
random_fops--random设备的操作函数集,major为1,minor为8。
/dev/random的ioctl支持命令如下:
- RNDGETENTCNT:用于获取熵池中的熵计数或熵的总量。
- RNDADDTOENTCNT:用于修改熵池数量。
- RNDGETPOOL:用于获取当前熵池的状态或内容。
- RNDADDENTROPY:用于向随机数生成器添加熵。这可能包括来自硬件源的熵或其他形式的随机数据。
- RNDZAPENTCNT:用于清除熵计数器为0。
- RNDCLEARPOOL:用于清空熵池和计数置为0.
- RNDRESEEDCRNG:用于reseeding加密随机数生成器(CRNG)。
2.1 /proc/sys/kernel/random
点击链接查看和 Kimi 智能助手的对话 https://kimi.moonshot.cn/share/cqud16cjot6qv0gkpnng
random_sysctls_init--创建/proc/sys目录下kernel/random目录,并创建random_table中节点。
random_table
random_table中包含一系列与随机数生成器相关参数,具体如下:
- boot_id:包含系统启动时生成的唯一标识符(boot ID)。它是基于系统启动时的多种因素(如时间、内存状态等)生成的,可用于确定随机数生成器的状态是否未被篡改。
- entropy_avail:显示当前熵池中的熵数量。熵是一个度量,表示随机源的不可预测性。/dev/random 在熵不足时会阻塞读取操作,直到熵池中的熵足够。
- poolsize:定义了熵池的大小,即熵池可以存储的熵的最大值。熵池的大小可能会影响到随机数生成器的性能和熵的收集速度。
- uuid:包含系统启动时生成的全局唯一标识符(UUID)。它类似于 boot ID,但用于更广泛的身份验证和识别目的。
- urandom_min_reseed_secs:设置了 /dev/urandom 自动重播种(reseeding)的最小时间间隔,单位为秒。重播种是指向熵池中注入新的熵以保证随机性的强度。这个设置防止 /dev/urandom 在短时间内过度重播种。
- write_wakeup_threshold:定义了当熵池中的熵低于某个阈值时,/dev/random 将触发写入唤醒(write wakeup)。这是一个回调机制,用于在熵池需要更多熵时通知系统。
2.3 /dev/random和/dev/urandom区别
/dev/random 和 /dev/urandom 是Linux和其他类Unix操作系统中的两个特殊的文件,它们提供了访问系统随机数生成器(RNG)的接口。这两个设备文件的主要区别在于它们生成随机数的方式和特性:
/dev/random
这是一个阻塞设备,当系统认为熵池(entropy pool)中的熵不足时,它会阻塞读取操作,直到收集到足够的熵来生成高质量的随机数。
/dev/random 被认为是一个更安全的随机数源,因为它确保了随机数的生成依赖于真正的熵,这使得随机数更难被预测。
由于它可能阻塞,所以它更适合用于需要高安全性的场合,如生成密钥或密码。
/dev/urandom
这是一个非阻塞设备,即使熵池中的熵不足,它也会继续生成随机数,但这些随机数的质量可能不如 /dev/random。
/dev/urandom 从Linux 2.6.26 开始,通过使用一个基于Yarrow算法的加密随机数生成器(CSPRNG)来提供更好的随机性,即使在熵不足的情况下也能继续生成随机数。
它适合大多数应用程序使用,因为它不会阻塞,可以提供足够的随机性,除非对随机数的安全性有极高的要求。
在实际使用中,大多数应用程序不需要 /dev/random 的阻塞特性,因此 /dev/urandom 通常是首选。然而,如果你需要生成极其敏感的数据,例如用于加密通信的密钥,那么使用 /dev/random 可能更合适。