亚洲综合在线一区二区三区-日韩超碰人人爽人人做人人添-麻豆国产精品久久人妻-无码人妻丰满熟妇啪啪-天堂精品一区二区三区-99久久综合狠狠综合久久aⅴ

×

從Linux內核中獲取真隨機數

分類:互聯網熱點 編輯:it知事 瀏覽量:55
2020-07-13 16:55:23
內核隨機數產生器 Linux內核實現了一個隨機數產生器,從理論上說這個隨機數產生器產生的是真隨機數。與標準C庫中的rand(),srand()產生的偽隨機數不同,盡管偽隨機數帶有一定的隨機特征,但這些數字序列并非統計意義上的隨機數。也就是說它們是可重現的--只要每次使用相同的seed值,就能得到相同的偽隨機數列。通常通過使用time()的返回值來改變seed,以此得到不同的偽隨機數序列,但time()返回值的結果并不是不確定的(可預測),也就是這里仍然缺少一個不確定的噪聲源。對于需要真隨機數的程序,都不能允許使用偽隨機數。   為了獲得真正意義上的隨機數,需要一個外部的噪聲源。Linux內核找到了一個完美的噪聲源產生者--就是使用計算機的人。我們在使用計算機時敲擊鍵盤的時間間隔,移動鼠標的距離與間隔,特定中斷的時間間隔等等,這些對于計算機來講都是屬于非確定的和不可預測的。雖然計算機本身的行為完全由編程所控制,但人對外設硬件的操作具有很大的不確定性,而這些不確定性可以通過驅動程序中注冊的中斷處理例程(ISR)獲取。內核根據這些非確定性 的設備事件維護著一個熵池,池中的數據是完全隨機的。當有新的設備事件到來,內核會估計新加入的數據的隨機性,當我們從熵池中取出數據時,內核會減少熵的估計值。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 asmlinkage int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,                             struct irqaction *action) {     int status = 1;     int retval = 0;           if (!(action->flags & SA_INTERRUPT))         local_irq_enable();       do     {         status |= action->flags;         retval |= action->handler(irq, action->dev_id, regs);         action = action->next;     }while (action);           if (status & SA_SAMPLE_RANDOM)         add_interrupt_randomness(irq);       local_irq_disable();     return retval; } 上面這段代碼是x86上用來處理某條中斷線上注冊的ISR例程的函數。這里我們感興趣的地方是:如果ISR在注冊期間指定了SA_SAMPLE_RANDOM標志,在處理完action后,還要調用add_interrupt_randomness()這個函數,它使用中斷間隔時間為內核隨機數產生器產生熵。內核就是在這里為熵池填充新數據的。 如果我們完全不操作計算機會如何呢?也就是作為噪聲源的產生者,我們完全不去碰鍵盤,鼠標等外設,不讓熵池獲得新的數據,這個時候如果去熵池取數據內核會如何反應? 內核在每次從熵池中取數據后都會減少熵的估計值,如果熵估計值等于0了,內核此時可以拒絕用戶對隨機數的請求操作。 獲取內核隨機數 有兩種方法可以從熵池中獲取內核隨機數。一種是通過內核導出的隨機數接口,另一種是通過特殊的設備文件/dev/random和/dev/urandom。下面分別討論兩種方法。 熵的輸出接口 1 void get_random_bytes(void *buf, int nbytes) 該函數返回長度為nbytes字節的緩沖區buf,無論熵估計是否為0都將返回數據。使用這個函數時需要在內核空間。我們寫一個小模塊來測試一下。   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 #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #define NUM 10   void get_random_bytes(void *buf, int nbytes);   static int get_random_number(void) {     unsigned long randNum;     int i = 0;       printk(KERN_ALERT "Get some real random number.\n");     for (i=0; i<NUM; i++)     {         get_random_bytes(&randNum, sizeof(unsigned long));         printk(KERN_ALERT "We get random number: %ld\n", randNum);     }     return 0; }   static void random_exit(void) {     printk(KERN_ALERT "quit get_random_num.\n"); }   module_init(get_random_number); module_exit(random_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Test"); Makefile如下:   1 2 3 4 5 6 7 8 9 10 obj-m = get_random_num.o KDIR = $(shell uname -r) PWD = $(shell pwd)   all:     make -C /lib/modules/$(KDIR)/build M=$(PWD) modules clean:     make -C /lib/modules/$(KDIR)/build M=$(PWD) clean   #end# 編譯之后加載模塊,通過dmesg命令輸出系統log最新的信息,可以看到我們的小模塊輸出了10個從內核熵池中得到的隨機數。卸載模塊后再次加載可以重新獲取新的隨機數,觀察輸出結果,與之前得到的隨機數完全不一樣。   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 Get some real random number. We get random number: -82199505 We get random number: -276237802 We get random number: 411869317 We get random number: 1779353222 We get random number: 823507551 We get random number: 1061461415 We get random number: 1372137935 We get random number: 1460835009 We get random number: 2002191729 We get random number: -272204344 quit get_random_num. Get some real random number. We get random number: 1111808207 We get random number: -13789055 We get random number: 240443446 We get random number: -606998911 We get random number: 538794850 We get random number: -500786675 We get random number: -1240394927 We get random number: 1233931345 We get random number: 1488497117 We get random number: -177688514 /dev/random & /dev/urandom 這兩個特殊設備都是字符型設備。我們可以在用戶空間通過read系統調用讀這兩個設備文件以此獲取隨機數。這兩個設備文件的區別在于:如果內核熵池的估計值為0時, /dev/random將被阻塞,而/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 34 35 36 37 38 39 #include <assert.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h>   /* 從min和max中返回一個隨機值 */   int random_number(int min, int max) {     static int dev_random_fd = -1;     char *next_random_byte;     int bytes_to_read;     unsigned random_value;           assert(max > min);           if (dev_random_fd == -1)     {         dev_random_fd = open("/dev/random", O_RDONLY);         assert(dev_random_fd != -1);     }           next_random_byte = (char *)&random_value;     bytes_to_read = sizeof(random_value);           /* 因為是從/dev/random中讀取,read可能會被阻塞,一次讀取可能只能得到一個字節,      * 循環是為了讓我們讀取足夠的字節數來填充random_value.      */     do     {         int bytes_read;         bytes_read = read(dev_random_fd, next_random_byte, bytes_to_read);         bytes_to_read -= bytes_read;         next_random_byte += bytes_read;     }while(bytes_to_read > 0);           return min + (random_value % (max - min + 1)); } 同樣,還可以用dd命令從/dev/urandom中獲取指定字節數的隨機值并寫入文件中保存--如果你需要以文件的形式提供隨機數的話。 dd if=/dev/urandom of = file count = 1 bs = bytes   關于內核隨機數產生器的詳細介紹,可參考Linux內核設計與實現第二版附錄B。

聲明:免責聲明:本文內容由互聯網用戶自發貢獻自行上傳,本網站不擁有所有權,也不承認相關法律責任。如果您發現本社區中有涉嫌抄襲的內容,請發

送郵件至:operations@xinnet.com進行舉報,并提供相關證據,一經查實,本站將立刻刪除涉嫌侵權內容。本站原創內容未經允許不得轉載,或轉載時

需注明出處:新網idc知識百科

免費咨詢獲取折扣

Loading
主站蜘蛛池模板: 伊人久久大香线蕉综合直播| 香蕉久久一区二区不卡无毒影院| 国产成人精品一区二区秒拍| 男女爱爱好爽视频免费看| 色综合久久久久综合99| 亚洲色成人一区二区三区| 欧美xxxx做受性欧美88| 人妻妺妺窝人体色www聚色窝| 久久人爽人人爽人人片av| 国产精品女人呻吟在线观看| 在线a人片免费观看| 亚洲精品无码久久毛片波多野吉衣| 无码男男作爱g片在线观看| 欧美在线一区二区免费视频| 精品亚洲国产成人av制服| 久久久综综合色一本伊人| 国产一区 制服丝袜| 99视频精品国产免费观看| 高潮流白浆潮喷在线播放视频| 毛片内射-百度| 无码乱人伦一区二区亚洲一| 亚洲成a人片在线观看久| 国产精品国产三级国产专区50| 无码av大香线蕉| 好吊妞视频这里有精品| 在线观看欧美日韩免费一区二区| 亚洲精品国产精品无码国模| 人妻一区二区出轨| 精品少妇一区二区三区免费观麻豆 | av片在线观看免费| 亚洲另类欧美在线电影| 日本欧美一区二区三区免费| 精品剧情v国产在线观看| av老司机亚洲精品天堂| 一本一道久久综合狠狠老| 99久久国语露脸精品国产| 国产综合视频一区二区三区| 理论片87福利理论电影| 在线播放免费播放av片| 偷拍女厕一区二区三区| 日韩欧美一区二区三区aⅴ|