/dev/random和/dev/urandom是Linux系统中提供的随机伪设备,这两个设备的任务,是提供永不为空的随机字节数据流。不少解密程序与安全应用程序(如SSH Keys,SSL Keys等)须要它们提供的随机数据流。php
这两个设备的差别在于:/dev/random的random pool依赖于系统中断,所以在系统的中断数不足时,/dev/random设备会一直封锁,尝试读取的进程就会进入等待状态,直到系统的中断数充分够用, /dev/random设备能够保证数据的随机性。/dev/urandom不依赖系统的中断,也就不会形成进程忙等待,可是数据的随机性也不高。安全
使用cat 命令能够读取/dev/random 和/dev/urandom的数据流(二进制数据流,很难阅读),能够用od命令转换为十六进制后查看:并发
在cat的过程当中发现,/dev/random产生的速度比较慢,有时候还会出现较大的停顿,而/dev/urandom的产生速度很快,基本没有任何停顿。dom
而使用dd命令从这些设备中copy数据流,发现速度差别很大:ssh
从/dev/random中读取1KB的字节流:函数
从/dev/urandom 中读取1KB的字节流:测试
经过程序测试也发现:/dev/random设备被读取的越多,它的响应越慢.加密
使用PHP的加密扩展mcrypt时,mcrypt_create_iv()函数用于从随机源建立初始向量(initialization vector),该函数的签名为:code
string mcrypt_create_iv ( int $size [, int $source = MCRYPT_DEV_URANDOM ] )
注意函数的第二个参数$source,在PHP 5.6.0如下的版本中,该参数默认是 MCRYPT_DEV_RANDOM,也就是说,mcrypt_create_iv默认从/dev/random设备获取随机数据源的。这在系统并发数较高时,系统没法提供足够的中断数,会致使访问进程挂起(锁住),从而没法正常响应。进程
一个简单的测试脚本以下:
1 <?php 2 define("MCRYPT_KEY","x90!-=zo2s"); 3 $src = "test"; 4 5 $size = mcrypt_get_iv_size(MCRYPT_BLOWFISH,MCRYPT_MODE_ECB); 6 $iv = mcrypt_create_iv($size); 7 $encrypted = mcrypt_ecb(MCRYPT_BLOWFISH, MCRYPT_KEY, $src, MCRYPT_DECRYPT, $iv);//5.5+已废弃,请使用最新的API测试
咱们以前在cat /dev/random的输出时已经发现,输出的随机数据流会出现较大的停顿。在并发数较大时,会形成读取进程的等待甚至没法响应。
幸亏,咱们能够指定第二个参数为MCRYPT_DEV_URANDOM使其强制使用/dev/urandom设备的随机数据流(PHP 5.6.0+版本中,已经默认使用/dev/urandom做为随机数据源)。
1. 这两个伪设备可用于代替mktemp产生随机临时文件名:
cat /dev/urandom |od –x | tr –d ' '| head –n 1
能够产生128位(bit)的临时文件名,具备较高的随机性和安全性。
2. 能够模拟生成SSH-keygen生成的footprint,脚本以下:
1 #/bin/sh - 2 cat /dev/urandom | 3 od -x | 4 head -n 1| 5 cut -d ' ' -f 2- | 6 awk -v ORS=":" 7 '{ 8 for(i=1; i<=NF; i++){ 9 if(i == NF){ 10 ORS = "\n"; 11 } 12 print substr($i,1,2) ":" substr($i,3,2); 13 } 14 }'
对该脚本的简单解释:
(1). cat /dev/urandom | od -x | head -n 1 用于从随机设备中读取一行数据流并转换为16进制。该段的输出相似于:
(2). 因为第一列其实是数据的偏移量,并非随机数据流,再次用cut取出后面的几个字段:cut -d ' ' -f 2-
(3). 利用awk程序输出。ORS是awk的内置变量,指输出记录分割符,默认为\n。
脚本的输出结果:
对比用ssh-keygen生成的footprint,是否是挺像的? :D