1. 基本介绍
/dev/random
和/dev/urandom
是Linux系统中提供的随机伪设备,这两个设备的任务,是提供永不为空的随机字节数据流。很多解密程序与安全应用程序(如SSH Keys,SSL Keys等)需要它们提供的随机数据流。
这两个文件记录Linux下的熵池,所谓熵池就是当前系统下的环境噪音,描述了一个系统的混乱程度,环境噪音由这几个方面组成,如内存的使用,文件的使用量,不同类型的进程数量等等,刚开机的时候系统噪音会较小。
这两个设备的差异在于:/dev/random
的random pool
依赖于系统中断,因此在系统的中断数不足时,/dev/random
设备会一直封锁,尝试读取的进程就会进入等待状态,直到系统的中断数充分够用, /dev/random
设备可以保证数据的随机性。/dev/urandom
不依赖系统的中断,也就不会造成进程忙等待,但是数据的随机性也不高。
2. 获取/dev/urandom和/dev/random中的值
1 | # dd count=1 ibs=1024 if=/dev/random >/dev/null |
1 | # dd count=1 ibs=1024 if=/dev/urandom >/dev/null |
可以看见/dev/urandom
生成随机数的速度要快很多,一般就使用/dev/urandom
获取随机数。
3. 在Python中如何生成随机数
我们首先了解一个知识点–伪随机数发生器。用于在系统需要随机数的时候,通过一系列种子值计算出来的伪随机数。因为生成一个真正意义上的“随机数”对于计算机来说是不可能的,伪随机数也只是尽可能地接近其应具有的随机性,但是因为有“种子值”,所以伪随机数在一定程度上是可控可预测的。
通过程序得到的随机数无论什么算法都一定是通过递推公式得到的序列,这本身就违反了随机的定义,所以它们都不是真正的随机数。伪随机数中一个很重要的概念就是“种子”,种子决定了随机数的固定序列,例如在C语言rand函数得到的序列每次都是相同的,如果想得到不同序列需要调用srand
设置种子;同理在Java中new Random(1)
的构造函数参数来设置种子 。
我们知道文件读取出来的是二进制数据,这个时候想转为随机数还需要一个模块–struct 。
python中的struct
主要是用来处理C结构数据的,读入时先转换为Python的字符串类型,然后再转换为Python的结构化类型,比如元组(tuple)啥的~。一般输入的渠道来源于文件或者网络的二进制流。
struct模块中最重要的三个函数是pack(), unpack(), calcsize()
1 | # 按照给定的格式(fmt),把数据封装成字符串(实际上是类似于c结构体的字节流) |
1 | def urandom_seed(): |
seed() 方法改变随机数生成器的种子,可以在调用其他随机模块函数之前调用此函数。
参考阅读:
Linux系统产生随机数/dev/random 和 /dev/urandom