您的位置 首页 嵌入式

从Linux内核中获取真随机数

内核随机数产生器Linux内核实现了一个随机数产生器,从理论上说这个随机数产生器产生的是真随机数。与标准C库中的rand(),srand()产生的伪随机数不同

内核随机数发生器

Linux内核完成了一个随机数发生器,从理论上说这个随机数发生器发生的是真随机数。与规范C库中的rand(),srand()发生的伪随机数不同,尽管伪随机数带有必定的随机特征,但这些数字序列并非核算意义上的随机数。也便是说它们是可重现的–只需每次运用相同的seed值,就能得到相同的伪随机数列。一般经过运用time()的回来值来改动seed,以此得到不同的伪随机数序列,但time()回来值的成果并不是不确认的(可猜测),也便是这儿依然短少一个不确认的噪声源。关于需求真随机数的程序,都不能答应运用伪随机数。

为了取得真实意义上的随机数,需求一个外部的噪声源。Linux内核找到了一个完美的噪声源发生者–便是运用核算机的人。咱们在运用核算机时敲击键盘的时刻距离,移动鼠标的距离与距离,特定中止的时刻距离等等,这些关于核算机来讲都是归于非确认的和不行猜测的。尽管核算机自身的行为彻底由编程所操控,但人对外设硬件的操作具有很大的不确认性,而这些不确认性能够经过驱动程序中注册的中止处理例程(ISR)获取。内核依据这些非确认性的设备事情维护着一个熵池,池中的数据是彻底随机的。当有新的设备事情到来,内核会估量新参加的数据的随机性,当咱们从熵池中取出数据时,内核会削减熵的估量值。

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都将回来数据。运用这个函数时需求在内核空间。咱们写一个小模块来测验一下。

?

#include

#include

#include

#define NUM 10

void get_random_bytes(void *buf, int nbytes);

static int get_random_number(void)

{

unsigned long randNum[10];

int i = 0;

printk(KERN_ALERT Get some real random number.\n);

for (i=0; 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如下:

?

obj-m = get_random_num.o

KDIR = $(shell uname -r)

PWD = $(shell pwd)

all:

make -C [img]file:///C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\)A[Y)I~](ZC9Z[3Y)IDK7LK.gif[/img]b/modules/$(KDIR)file:///C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\OOY5$4OW5H`8`9%(9$)T67M.gifild M=$(PWD) modules

clean:

make -C [img]file:///C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\)A[Y)I~](ZC9Z[3Y)IDK7LK.gif[/img]b/modules/$(KDIR)file:///C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\OOY5$4OW5H`8`9%(9$)T67M.gifild M=$(PWD) clean

#end#

编译之后加载模块,经过dmesg指令输出体系log最新的信息,能够看到咱们的小模块输出了10个从内核熵池中得到的随机数。卸载模块后再次加载能够从头获取新的随机数,调查输出成果,与之前得到的随机数彻底不一样。

[37972.467955] Get some real random number.

[37972.468392] We get random number: -82199505

[37972.468580] We get random number: -276237802

[37972.468586] We get random number: 411869317

[37972.468590] We get random number: 1779353222

[37972.468594] We get random number: 823507551

[37972.468598] We get random number: 1061461415

[37972.468602] We get random number: 1372137935

[37972.468606] We get random number: 1460835009

[37972.468610] We get random number: 2002191729

[37972.468614] We get random number: -272204344

[38059.349589] quit get_random_num.

[38070.575433] Get some real random number.

[38070.575462] We get random number: 1111808207

[38070.575476] We get random number: -13789055

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/298407.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部