当前位置:首页 > 嵌入式 > 嵌入式软件
[导读] 内核随机数产生器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[!--empirenews.page--]

[38070.575481] We get random number: 240443446

[38070.575485] We get random number: -606998911

[38070.575489] We get random number: 538794850

[38070.575493] We get random number: -500786675

[38070.575497] We get random number: -1240394927

[38070.575501] We get random number: 1233931345

[38070.575504] We get random number: 1488497117

[38070.575508] We get random number: -177688514

/dev/random & /dev/urandom

这两个特殊设备都是字符型设备。我们可以在用户空间通过read系统调用读这两个设备文件以此获取随机数。这两个设备文件的区别在于:如果内核熵池的估计值为0时,

/dev/random将被阻塞,而/dev/urandom不会有这个限制。

#include

#include

#include

#include

#include

/* 从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

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭