偽隨機數(shù),程序員哪個不知,哪個不曉。在linux下,設置好隨機種子,然后調用rand()函數(shù),但你真的知道了解它嗎?其實你錯了,這個"偽"確實夠偽的,騙了很多人,不信,看如下代碼:
1 2 3 4 5 6 7 | #include <stdio.h> #include <stdlib.h> int main(void) { srand(100); printf ( "%d\n" ,rand()); return EXIT_SUCCESS; } |
你把代碼運行10遍,發(fā)現(xiàn)啥了?咦,怎么每次的結果都一樣啊,這樣別人如果知道種子(100)了,就知道結果了,這樣的結果配叫隨機數(shù)啊。常用的方法就是種子用時間來計算,但安全性不高,你我都知道你會用時間做種子算法,那還安全啊,我每次打游戲老怪就老蹲在一個地方打,反正你是"隨機坐標"出來的怪獸嘛!顯然問題相當嚴重了,那咋辦?
最簡單的辦法:種子也用隨機數(shù)來表示。這,我不說你都知道問題了,本來就是求隨機數(shù)都沒出來,你還整個隨機種子,表妹知道肯定說打死我。哎,好在linux給我們提供了“真正的”隨機數(shù),在內核中,linux會維護一些偶然出現(xiàn)的數(shù)據,并且為用戶提供訪問接口。之所以稱之為真正的隨機數(shù),是因為這些數(shù)據來源于計算機本身的偶然操作,比如硬盤操作、鍵盤和鼠標的操作,等等。這些操作比起那些通過固定算法生成的偽隨機數(shù)來說,當然是更真實一些了,它被叫做“熵”。內核提供的接口是/dev/random和/dev/urandom設備,二者的區(qū)別是讀取時random肯定會返回一個數(shù),如果沒有足夠的數(shù)據,就會阻塞。而urandom則不會阻塞,但是不保證返回的是合適的數(shù)據。下面就針對這兩個接口來看看真正的隨機數(shù)是怎么產生的:
一,使用/dev/random接口,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #include <stdio.h> #include <sys/time.h> #include <fcntl.h> unsigned int new_rand () { int fd; unsigned int n = 0; fd = open ( "/dev/random" , O_RDONLY); if (fd > 0) { read (fd,&n,sizeof (n)); } close (fd); return n; } int main () { int n, i; //init_random (); srand(new_rand()); n = rand (); printf ( "n=%d " ,rand()); return 0; } |
這一種方法夠簡單明了,通過讀取linux中真正的偽隨機接口/dev/random來真正的隨機產生種子,種子都隨機了,結果還不隨機啊。但問題明顯,我剛說了,讀取時random肯定會返回一個數(shù),如果沒有足夠的數(shù)據,就會阻塞。這個阻塞有時是會帶來安全問題的。
二,使用/dev/urandom接口,代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #include <stdio.h> #include <sys/time.h> #include <fcntl.h> void init_random () { unsigned int ticks; struct timeval tv; int fd; gettimeofday (&tv, NULL); ticks = tv.tv_sec + tv.tv_usec; fd = open ( "/dev/urandom" , O_RDONLY); if (fd > 0) { unsigned int r; int i; for (i = 0; i < 512; i++) { read (fd, &r, sizeof (r)); ticks += r; } close (fd); } srand (ticks); } int main () { int n, i; init_random (); n = rand (); printf ( "n=%d " , n); return 0; } |
這個方法相比較第一種而言,很明顯獲取隨機種子時麻煩一些,表現(xiàn)在居然循環(huán)了512次,遮掩做主要是因為剛說過讀取/dev/urandom設備會立即返回,但并不保證會得到合適的數(shù),所以多做幾次,保證能獲得需要的數(shù)。