UNXI生成随机数.doc
上传人:sy****28 上传时间:2024-09-11 格式:DOC 页数:3 大小:26KB 金币:16 举报 版权申诉
预览加载中,请您耐心等待几秒...

UNXI生成随机数.doc

UNXI生成随机数.doc

预览

在线预览结束,喜欢就下载吧,查找使用更方便

16 金币

下载此文档

如果您无法下载资料,请参考说明:

1、部分资料下载需要金币,请确保您的账户上有足够的金币

2、已购买过的文档,再次下载不重复扣费

3、资料包下载后请先用软件解压,在使用对应软件打开

使用/dev/random生成随机数很多库例程产生的“随机”数是准备用于仿真、游戏等等;它们在被用于密钥生成一类的安全函数时是不够随机的。其问题在于这些库例程使用的算法的未来值可以被攻击者轻易地推导出来(虽然看起来它们可能是随机的)。对于安全函数,需要的随机值应该是基于量子效应之类的确实无法预测的值。Linux内核(1.3.30以上)包括了一个随机数发生器/dev/random,对于很多安全目的是足够的。/dev/random是如何创建随机数的呢?Linux操作系统提供本质上随机(或者至少具有强烈随机性的部件)的库数据。这些数据通常来自于设备驱动程序。例如,键盘驱动程序收集两个按键之间时间的信息,然后将这个环境噪声填入随机数发生器库。随机数据存储在熵池中,它在每次有新数据进入时进行“搅拌”。这种搅拌实际上是一种数学转换,帮助提高随机性。当数据添加到熵池中后,系统估计获得了多少真正随机位。测定随机性的总量是很重要的。问题是某些量往往比起先考虑时看上去的随机性小。例如,添加表示自从上次按键盘以来秒数的32位数实际上并没有提供新的32位随机信息,因为大多数按键都是很接近的。从/dev/random中读取字节后,熵池就使用MD5算法进行密码散列,该散列中的各个字节被转换成数字,然后返回。如果在熵池中没有可用的随机性位,/dev/random在池中有足够的随机性之前等待,不返回结果。这意味着如果使用/dev/random来产生许多随机数,就会发现它太慢了,不够实用。我们经常看到/dev/random生成几十字节的数据,然后在许多秒内都不产生结果。幸运的是有熵池的另一个接口可以绕过这个限制:/dev/urandom。即使熵池中没有随机性可用,这个替代设备也总是返回随机数。如果您取出许多数而不给熵池足够的时间重新充满,就再也不能获得各种来源的合用熵的好处了;但您仍可以从熵池的MD5散列中获得非常好的随机数!这种方式的问题是,如果有任何人破解了MD5算法,并通过查看输出了解到有关散列输入的信息,那么您的数就会立刻变得完全可预料。大多数专家都认为这种分析从计算角度来讲是不可行的。然而,仍然认为/dev/urandom比/dev/random要“不安全一些”(并通常值得怀疑)。应用中出现的问题:在我们的服务器程序中,用户登陆的时候会读取/dev/random产生随机数,问题来了,当用户登陆比较密集,这时候read就会返回特别慢,并且返回的字节数也比要求的少,甚至不返回――阻塞。我们把用户登陆处理函数放在了线程池里,导致的问题就是线程池里所有线程都可能会阻塞,这就造成了拒绝服务攻击。导致其他用户登陆失败。解决方案:1#include<stdio.h>2#include<string.h>3#include<sys/types.h>4#include<sys/stat.h>5#include<sys/file.h>6#include<sys/time.h>7#include<errno.h>8#include<unistd.h>9#include<stdlib.h>1011staticintget_random_fd(void)12{13staticintfd=-2;1415if(fd==-2)16{17fd=open("/dev/random",O_RDONLY|O_NONBLOCK);18if(fd==-1)19fd=open("/dev/urandom",O_RDONLY|O_NONBLOCK);20}2122returnfd;23}2425/*26*Generateaseriesofrandombytes.Use/dev/randomifpossible,27*andifnot,use/dev/urandom.28*/29voidget_random_bytes(void*buf,intnbytes)30{31inti,fd=get_random_fd();32intlose_counter=0;33char*cp=(char*)buf;34structtimevaltv;35staticunsignedseed=0;3637if(fd>=0)38{39while(nbytes>0)40{41i=read(fd,cp,nbytes);42if((i<0)&&43((errno==EINTR)||(errno==EAGAIN)))44continue;4546if(i<=0)47{48if(lose_counter++==8)49break;5051continue;52}53nbytes-=i;54cp