最近在研究python源码,其中在初始化阶段会用到随机数生成器,三种方法:
一种是getrandom函数;具体信息可查看手册getrandom(2) - Linux manual page (man7.org)
一种是/dev/random或/dev/urandom:是Linux系统中提供的随机伪设备,这两个设备的任务,是提供永不为空的随机字节数据流。很多解密程序与安全应用程序(如SSH Keys,SSL Keys等)需要它们提供的随机数据流。
1. /dev/random的工作原理
/dev/random
是一个阻塞式的随机数生成器。它使用熵池(entropy pool)来收集系统中的各种随机事件,如键盘输入、鼠标移动、网络数据包到达时间等。当这些随机事件发生时,它们会被加入熵池,并由一个算法将其转化为随机数。如果熵池中的随机性不足,读取/dev/random
将会阻塞,直到有足够的随机性为止。
2. /dev/urandom的工作原理
与/dev/random
不同,/dev/urandom
是一个非阻塞式的随机数生成器。它同样使用熵池来收集随机事件,但在熵池中的随机性不足时,它会通过算法生成伪随机数来填补空缺。因此,/dev/urandom
可以立即提供随机数,不需要等待。
3. /dev/random与/dev/urandom的区别
- 阻塞与非阻塞:如上所述,
/dev/random
在随机性不足时会阻塞,而/dev/urandom
不会。 - 随机性:由于
/dev/random
严格依赖于系统中的随机事件,因此它生成的随机数在随机性上通常更高。而/dev/urandom
在随机性不足时可能产生伪随机数,因此在极端情况下其随机性可能不如/dev/random
。 - 性能:由于
/dev/urandom
不需要等待随机事件积累,因此它的性能通常优于/dev/random
。
4.使用
使用cat 命令可以读取/dev/random 和/dev/urandom的数据流(二进制数据流,很难阅读),可以用od命令转换为十六进制后查看:
$ cat /dev/urandom | od -x |head - n 10
0000000 37bc e743 8e90 0b4f fb7d bfe1 bc0c 3ced
0000020 6467 593b 0076 f6a6 d338 35fb 1fa5 93f8
0000040 15e9 6b46 f6a8 069b c74b a29d fc98 b2b1
0000060 7a2d f9fe d7e0 4285 d950 b726 40f8 7545
0000100 3e89 99c0 c449 aaee c3ec 4117 5a78 46d4
0000120 85b7 5902 41ae 8c02 d9c1 f3b4 efbc 3ea2
0000140 8305 eadd 413d 1bd5 433f 7d6b ec9b a7f9
0000160 eb57 ce62 20d7 3689 5ded a1a7 baac 674c
0000200 8300 6f36 4d55 d2df 5093 8f56 ee83 e60a
0000220 09f3 55ef df9c be9a 9630 43b9 512e 3af2
这两个伪设备可用于代替mktmp产生随机临时文件名:
$ cat /dev/urandom | od -x | tr -d ' '|head -n 1
0000000f3083f34591350dc7eb15f41dc6a7769