什么是随机数

很多软件和应用都需要随机数,从纸牌游戏中纸牌的分发到 SSL 安全协议中密钥的产生,到处都有随机数的身影。随机数至少具备两个条件:

  1. 数字序列在统计上是随机的
  2. 不能通过已知序列推算后面的序列

自从计算机诞生起,寻求用计算机产生高质量的随机数序列的研究就一直是研究者长期关注的课题。一般情况下,使用计算机程序产生一个真正的随机数是很难的,因为程序的行为是可预测的,计算机利用设计好的算法结合用户提供的种子产生的随机数序列通常是“伪随机数”(pseudo-random number),伪随机数就是我们平时经常使用的“随机数”。伪随机数可以满足一般应用的需求,但是在对于安全要求比较高的环境和领域中存在明显的缺点:

  1. 伪随机数是周期性的,当它们足够多时,会重复数字序列
  2. 如果提供相同的算法和相同的种子值,将会得出完全一样的随机数序列
  3. 可以使用逆向工程,猜测算法与种子值,以便推算后面所有的随机数列

只有实际物理过程才是真正的随机,只有借助物理世界中事物的随机性才能产生真正的随机数,比如真空内亚原子粒子量子涨落产生的噪音、超亮发光二极管在噪声的量子不确定性和放射性衰变等。

随机数为什么如此重要

生成随机数是密码学中的一项基本任务,是生成加密密钥、加密算法和加密协议所必不可少的,随机数的质量对安全性至关重要。最近报道有人利用随机数缺点成功攻击了某网站,获得了管理员的权限。美国和法国的安全研究人员最近也评估了两个 Linux 内核 PRNG——/dev/random 和/dev/urandom 的安全性,认为 Linux 的伪随机数生成器不满足鲁棒性的安全概念,没有正确积累熵。可见随机数在安全系统中占据着非常重要的地位。

Linux 中随机数如何产生

PRNG(Pseudo-Random Number Generator)

1994 年,美国软件工程师 Theodore Y. Ts'o 第一次在 Linux 内核中实现了随机数发生器,使用 SHA-1 散列算法而非密码,提高了密码强度。

Linux 内核采用熵来描述数据的随机性,熵(entropy)是描述系统混乱无序程度的物理量,一个系统的熵越大则说明该系统的有序性越差,即不确定性越大。内核维护了一个熵池用来收集来自设备驱动程序和其它来源的环境噪音。理论上,熵池中的数据是完全随机的,可以实现产生真随机数序列。为跟踪熵池中数据的随机性,内核在将数据加入池的时候将估算数据的随机性,这个过程称作熵估算。熵估算值描述池中包含的随机数位数,其值越大表示池中数据的随机性越好。 内核中随机数发生器 PRNG 为一个字符设备 random,代码实现在 drivers/char/random.c,该设备实现了一系列接口函数用于获取系统环境的噪声数据,并加入熵池。系统环境的噪声数据包括设备两次中断间的间隔,输入设备的操作时间间隔,连续磁盘操作的时间间隔等。 对应的接口包括:

void add_device_randomness(const void *buf, unsigned int size);

void add_input_randomness(unsigned int type, unsigned int code,

unsigned int value);

void add_interrupt_randomness(int irq, int irq_flags);

void add_disk_randomness(struct gendisk *disk);

内核提供了 1 个的接口来供其他内核模块使用。

void get_random_bytes(void *buf, int nbytes);

该接口会返回指定字节数的随机数。random 设备了提供了 2 个字符设备供用户态进程使用——/dev/random 和/dev/urandom:

  • /dev/random 适用于对随机数质量要求比较高的请求,在熵池中数据不足时, 读取 dev/random 设备时会返回小于熵池噪声总数的随机字节。/dev/random 可生成高随机性的公钥或一次性密码本。若熵池空了,对/dev/random 的读操作将会被阻塞,直到收集到了足够的环境噪声为止。这样的设计使得/dev/random 是真正的随机数发生器,提供了最大可能的随机数据熵。
  • /dev/urandom,非阻塞的随机数发生器,它会重复使用熵池中的数据以产生伪随机数据。这表示对/dev/urandom 的读取操作不会产生阻塞,但其输出的熵可能小于/dev/random 的。它可以作为生成较低强度密码的伪随机数生成器,对大多数应用来说,随机性是可以接受的。

/dev/random 也允许写入,任何用户都可以向熵池中加入随机数据。即使写入非随机数据亦是无害的,因为只有管理员可以调用 ioctl 以增加熵池大小。Linux 内核中当前熵的值和大小可以通过访问 /proc/sys/kernel/random/得到,比如:

# cat /proc/sys/kernel/random/poolsize

4096

# cat /proc/sys/kernel/random/entropy_avail

298

# cat /proc/sys/kernel/random/uuid

4f0683ae-6141-41e1-b5b9-57f4bd299219

但是 Linux 内核中随机发生器中存在几个弱点,在嵌入式系统(缺少鼠标键盘),Live CD 系统(缺少磁盘),路由器,无盘工作站和一些服务器系统中,环境熵的来源较为受限,随机数质量会有所下降。对于有 NVRAM 的系统,建议在关机时保存一部分随机数发生器的状态,使得在下次开机时可以恢复这些状态。对于路由器而言,可以考虑把网络数据可以作为熵的主要来源。

EGD

EGD(熵收集守护进程,entropy gathering daemon)通常可以在不支持/dev/random 设备的 Unix 系统中提供类似的功能。这是一个运行于用户态的守护进程,提供了高质量的密码用随机数据。一些加密软件,比如 OpenSSL,GNU Privacy Guard 和 Apache HTTP 服务器支持在/dev/random 不可用的时候使用 EGD。

EGD,或者类似的软件 prngd,可以从多种来源收集伪随机的熵,并对这些数据进行处理以去除偏置,并改善密码学质量,然后允许其它程序通过 Unix 域套接口(通常使用/dev/egd-pool),或 TCP 套接口访问其输出。该程序通常使用建立子进程的以查询系统状态的方式来收集熵。它查询的状态通常是易变和不可预测的,例如 CPU,I/O,网络的使用率,也可能是一些日志文件和临时目录中的内容。

EGD 通过一个简单的协议与那些需要随机数的客户端进行通信,客户端通过连接 EGD socket 发送命令(从前八位来识别命令):

  • command 0: 查询当前可用熵
  • command 1: 非阻塞地获取随机字节数
  • command 2: 阻塞地获取随机字节数
  • command 3: 更新熵

硬件随机数产生器

当前有很多硬件随机数产生器(hwrng)用于产生可靠的随机数,但都是商用的,价格比较昂贵,最常使用的是 ComScire QNG,截止笔者写这篇文章,ComScire PQ4000KU 的官方价格接近 900 美元。

Intel’s Ivy Bridge family 有一个功能叫”Secure Key”, 处理器包含了一个内部硬件 DRNG(Digital Random Number Generator)用于产生随机数,使用汇编指令 RDRAND 即可获得高强度的随机数,Linux Kernel 会使用异或操作把 RDRAND 产生的随机数混合进熵池, 代码实现在 drivers/char/random.c 的 extract_entropy()函数里。

1

2

3

4

5

6

for (i = 0; i < LONGS(EXTRACT_SIZE); i++) {

unsigned long v;

if (!arch_get_random_long(&v))

break;

hash.l[i] ^= v;

}

还有一些第三方的硬件随机数生成器,通常是 USB 或者 PCI 设备,主要是在服务器上使用。Linux Kernel 的 hwrng(hardware random number generator)抽象层(/dev/hwrng 设备)可以选择监控 RNG 设备,并且在熵池数据不足的时候要求设备提供随机数据到 kernel 的熵池,rngd 守护进程可以读取 hwrng 的数据然后补给到 kernel 的熵池中。

在 KVM 虚拟机中如何应用

虚拟机环境下和服务器情况类似,输入设备操作很少,相对于 Host 而言,Disk I/O 也相对较少,因此依赖 Guest 自身 PRNG 产生的随机数质量不高,因此虚拟机通常从 Host(宿主机)获取部分随机数据。对于 KVM 虚拟机来说,存在一个半虚拟化设备 virtio-rng 作为硬件随机数产生器。Linux Kernel 从 2.6.26 开始支持 virtio-rng, QEMU 在 1.3 版本加入了对 virtio-rng 的支持。 virtio-rng 设备会读取 Host 的随机数源并且填充到 Guest(客户机)的熵池中。通常情况下使用/dev/random 作为输入源。当然,数据源可以更改,当 Host 系统中存在 hwrng 的情况下你可以使用/dev/hwrng 来作为 virtio-rng 的输入源。 也可以把 hwrng 设备 pass-through(透传)到客户机中,但是并不实用,比如在虚拟机 Live Migration(实时迁移)时会存在问题。在 Guest 中添加 virtio-rng 设备具体操作,使用/dev/random 作为输入源,两种方法:

  1. 使用 libvirt 编辑虚拟机的 XML

    1

    2

    3

    4

    5

    在虚拟机 XML 定义中,在<devices>段中添加:

    <rng model='virtio'>

    <backend model='random'>/dev/random</backend>

    </rng>

  2. 使用 QEMU command Line 直接添加:

    1

    2

    -object rng-random,filename=/dev/random,id=rng0 \

    -device virtio-rng-pci,rng=rng0

虚拟机启动后,在 Host 端:

1

2

3

$ lsof /dev/random

COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME

qemu-syst 23590 mars   11r   CHR    1,8      0t0 1032 /dev/random

会看到当前 QEMU 进程正在使用/dev/random 设备。

1

2

3

4

5

6

7

8

Guest 端:

$ cat /sys/devices/virtual/misc/hw_random/rng_available

virtio

$ cat /sys/devices/virtual/misc/hw_random/rng_current

virtio

$ lsmod | grep virtio_rng

virtio_rng  12790   0

....

可以看到 Guest 已经识别到硬件随机数产生器。

1

$ dd if=/dev/hwrng of=/home/random-data bs=1

添加 bs 选项并且最好设置的值比较小,因为 Host 上随机数资源可能会比较少,如果 bs 设置值太大,短时间内可能无法获得足够的数据写入文件,同时在 Host 端多做一些鼠标键盘或者磁盘的操作,会更快地产生随机数。

1

2

3

$ hexdump /home/random-data

00000000    9501 e702 ....

00000010    .... .... ....

使用 EGD 协议来作为输入源

  • 使用 libvirt 编辑虚拟机的 XML:

    1

    2

    3

    4

    5

    <rng model='virtio'>

       <backend model='egd' type='tcp'>

         <source mode='connect' host='127.0.0.1' service='8000'/>

       </backend>

     </rng>

  • 使用 QEMU command Line 直接添加:

    1

    2

    3

    -chardev socket,host=localhost,port=1024,id=chr0 \

    -object rng-egd,chardev=chr0,id=rng0 \

    -device virtio-rng- pci,rng=rng0

总结

随机数在计算机系统中有着非常重要的作用,本文阐述了随机数的概念和重要性,介绍了在 Linux 中产生随机数的方法,以及在 KVM 环境下虚拟机如何使用 virtio-rng 来获取随机数据。

Linux 系统中随机数在 KVM 中的应用相关推荐

  1. windows查看linux文件中文,Linux 系统下无法查看Windows 中创建的中文文件名

    标  题: Linux 系统下无法查看Windows 中创建的中文文件名 我是Linux初学者,在网上搜索了很久,经过多次尝试仍然无法解决问题,只好在这里发贴请教了,还望各位高手指点一下. 问题描述: ...

  2. 在重启Linux系统中把内存,在重新启动Linux系统的同时把内存中的信息写入硬盘,应使用()...

    在重新启动Linux系统的同时把内存中的信息写入硬盘,应使用()由河北公务员考试网公务员行测试题栏目提供,更多关于国考银保监试题,河北公务员考试公务员行测试题的内容,请关注河北公务员考试网/河北人事考 ...

  3. 重新启动linux系统应使用 命令实现,在重新启动Linux系统的同时把内存中的信息写入硬盘,应使用哪个命令...

    [导读]华图河南人事考试网同步华图教育发布:在重新启动Linux系统的同时把内存中的信息写入硬盘,应使用哪个命令,详细信息请阅读下文!如有疑问请加[交流群汇总],更多资讯请关注河南华图微信公众号(hn ...

  4. linux系统下安装pfam数据库中hmmer软件以及python3非root用户的安装

    linux系统下安装pfam数据库中hmmer软件以及python3非root用户的安装 http://hmmer.org/从该链接下载源,其中有Userguide.pdf 下载,解压缩并切换目录 之 ...

  5. Linux系统 虚拟化篇之KVM

    完全虚拟化 VMware  半虚拟化 xen  硬件辅助虚拟化Kvm #查看物理机是否支持虚拟化 处理器虚拟化 VT-X I/O虚拟化 VT-d 网络虚拟化 VT-C /etc/udev/rules. ...

  6. linux 命令行随机数,Linux系统产生随机数的6种方法

    Linux系统产生随机数的6种方法 1.通过系统环境变量($RANDOM)产生随机数 [root@localhost ~]# echo $RANDOM 3849 [root@localhost ~]# ...

  7. linux kvm安装windows,Debian Linux系统上的虚拟机KVM(完美安装windows系统)

    一.KVM基本知识 关于KVM的基础知识,在这里不想做过多的介绍,那是你自己需要去了解的,这里我只将一些参考文档罗列出来:<>,<>,<>,<>,< ...

  8. [转载] python中随机数生成函数_python中seed随机函数如何生成随机数?

    参考链接: Python中的随机数 如果要考察某公司的牛奶产品质量,可以从100袋牛奶中抽取30袋,在随机数表中选中一数,并用向上.下.左.右不同的读法组成30个数,并按牛奶的标号进行检测,虽然麻烦, ...

  9. 删除ubuntu linux系统,从Windows双启动中卸载Ubuntu Linux

    我在过去已经多次涉及到在UEFI模式下安装Ubuntu 14.04与Windows 8/8.1双启动的话题(见http://www.linuxidc.com/Linux/2014-09/107055. ...

  10. Linux 系统 uos / deepin 系统安装过程中 最全常用命令及问题 总结

    本博客已暂停更新,为了您更好的阅读,请转至新博客https://www.whbwiki.com/1296.html 此教程用来解决uos/deepin系统安装过程中的一系列问题,其他linux发行版适 ...

最新文章

  1. INTERVAL数据类型-007学习笔记
  2. 气泡提示效果css.html,用纯CSS3绘制高端简约的气泡提示框
  3. oracle 创交表,创建交叉报表(oracle)_oracle
  4. 作为一名前端开发工程师,你必须掌握的WEB模板引擎:Handlebars
  5. 外围功能电路控制 LET′S TRY“嵌入式编程”: 4 of 6
  6. 微软老兵 Antoine LeBlond 将正式离职
  7. MySQL的错误:No query specified
  8. 信息学奥赛 数论专题 2、带 余 除 法
  9. TPC-C 中跑赢 Oracle 的 OceanBase,双 11 处理峰值达 6100 万次/秒!
  10. hdfs及yarn的ha和failover
  11. java代码混淆工具ProGuard混淆插件
  12. CQF笔记M1L4随机分析和伊藤引理
  13. 坚守13年的极飞,终靠“务农”拿下12亿融资!专访彭斌:要为行业找技术,而不是为技术找行业...
  14. Android ListView异步获取网络图片
  15. [STT, AST, SpeechToText]的几个简单例子
  16. 阿里云视频点播服务SDK的使用,视频文件上传测试
  17. html中点击文字变色,html选中文字 背景/字 变色
  18. 连锁实体门店+收银系统的解决方案
  19. MongoDB——更新操作详解
  20. DataFrame详解——缺失数据处理

热门文章

  1. 18. jQuery - 尺寸
  2. c++ builder 存储过程 mysql mssql_C++ Builder实现Microsoft SQL Server 2000 的扩展存储过程...
  3. BZOJ1565 [NOI2009]植物大战僵尸(拓扑排序 + 最大权闭合子图)
  4. html5晋级之路-学习笔记表单
  5. PowerDesigner中Table视图同时显示Code和Name
  6. Runtime中神奇的exec方法
  7. 全网最全教你轻松把vue项目部署到IIS服务器
  8. Linux下编译googletest
  9. 关于读取配置文件的一个小笔记
  10. python绘制玫瑰花代码视频_python turtle玫瑰花绘制效果和源代码