/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