Linux系统中的熵池机制及其作用简介 (linux 熵池)

在Linux系统中,随机数生成是很重要的一项功能。不同的应用程序需要随机数来保证其安全性以及稳定性。随机数生成过程中,需要用到熵池(Entropy Pool)来提供随机性的源头。本文将详细介绍Linux系统中熵池机制的作用及其原理。

一、熵池的概念

熵池是随机数生成器的核心,所以它的定义非常重要。熵池是一种计算机系统内部的状态,包含所有可能的随机性的来源。它可以包括一系列与时间和空间有关的因素,例如硬盘存储器和其他外部设备上的读写操作,鼠标移动,键盘敲击,网络数据传输,以及其他具有随机性的用户活动。这些因素产生的熵将加入熵池,为随机数生成器提供更加高质量的随机数。

二、熵池的产生原理

熵池的作用在于提供足够的随机性来产生可靠随机数,但是熵池本身的生成机制需要考虑一些特殊因素。有两种情况需要注意:

1. 无法保证源头的真正随机性

熵池的来源很多,但并不是所有的因素都是真正的随机性来源。有些数据看上去很随意,但可能具有重复性和可预见性,因此可能不适用于熵池。比如,某些系统通常使用用户提供的随机数值,但是如果所有的用户都使用相同的型号的硬件、相似的软件设置以及相同的密钥集,那么此时用户提供的随机数值实际上并不具备随机性。

2. 无法保证真正随机性的持续存在性

随机性在时间上是不同步的,以至于在一个生成随机数的时刻可能非常充足,但是在下一个生成的时刻却几乎用光了。由于随机性的分布,不能保证在产生许多伪造随机数的情况下保持高质量的随机性。

为了解决以上问题,Linux中的熵池通过多种因素产生随机数,然后将其放入熵池进行混合和威迫。混合和威迫是将生成的数据尽可能混合,增加其中的熵,提高其质量。

三、熵池对系统的作用

随机数在Linux系统中的应用广泛。有些场景中,随机数生成是系统的最重要任务之一。例如,加密的密钥、数字签名、同时需要针对攻击进行防御的应用程序。在许多实例中,使用不可靠的随机数或伪随机数可能会严重危害安全。

另一方面,随机数还用于其他许多系统任务,如进程调度和内存分配。这些任务没有像加密密钥和数字签名那样关键重要,但是伪随机性可能会导致这些任务之间的冲突。用户还可能因为需要随机数来进行一些具有特定意义的任务(例如游戏和音乐软件),所以不可靠的随机性将会对用户体验产生明显影响。

为了应对以上场景,Linux系统中的熵池通过混合多个随机性源头,以过滤掉低品质的信息,保证可靠的随机性输出。

四、

Linux熵池机制在保障随机数生成质量方面非常重要。在本文中,我们已经初步了解了熵池的概念及其产生原理。现在,您应该已经知道熵池在Linux系统中的重要作用、以及它如何保障软件安全和用户体验。在Linux中,熵池是一种通用的可靠随机数生成机制,从而能够满足众多应用程序的需求。

相关问题拓展阅读:

请问C语言中clock()函数该怎么用?

The clock() function returns an approximation of processor time used by the program.

以上内容摘自 man 3 clock

返回接近程序使用的CPU时间 你拿这个做种子?

如果linux下 建议

GRand*g_rand_new(void);

Creates a new random number generator initialized with a seed taken either from /dev/urandom (if existing) or from the current time (as a fallback).

使用这个函数 直接使用操作系统提供的/dev/urandom 这个设备是根据环境噪声产生的真(记得好像是)随机数

如果没有urandom就使用当前时间 具体这个时间精确到多少不知道

如果不用glib库

就直接去读/dev/urandom设备 这个做种子是更好了的

linux里面一般都用这个/dev/random 和/dev/urandom得到真随机数 这个这个设备的种子是 通过中断事件得到的 网卡 键盘 等设备的中断是异步 产生的随机数应该可以算作真随机数了

不过这个只适应linux而且 程序环境必须是在有交换性 也就是外界必须提供中断事件 而且如果熵池里面的随机数用完了 读取这个设备会造成程序阻塞 直到熵池里有新的随机数

如果你的程序适应这种条件

可以使用glib 有交换环境 linux (一般不是特殊环境下都满足)

建议直接使用这个方便的函数了

glib就是为了方便程序员 跨平台跑程序的 在window下可以用

clock()函数没什么好说的我直接把man里面note节翻译给你看下

Note that the time can wrap around. On a 32-bit system where CLOCKS_PER_SEC equalsthis function will return the same value approximately every 72 minutes.

每72分钟会产生相同的值 (所以肯定是伪随机数,不过可以达到一般程序要求了)

On several other implementations, the value returned by clock() also includes the times of any children whose status has been collected via wait(2) (or another wait-type call). Linux does not include the times of waited-for children in the value returned by clock(). The times(2) function, which explicitly returns (separate) information about the caller and its children, may be preferable.

The C standard allows for arbitrary values at the start of the program; subtract the value returned from a call to clock() at the start of the program to get maximum portability.

C标准允许在程序开始设置一个任意值减去”clock()”的返回值 作为结果

以方便移植

The value returned is the CPU time used so far as a clock_t; to get the

number of seconds used, divide by CLOCKS_PER_SEC. If the processor

time used is not available or its value cannot be represented, the

function returns the value (clock_t) -1.

函数的返回值 使用的秒数除以CLOCKS_PER_SEC (32位系统这个数是)

如果time不可用 返回(clock_t) -1

linux里面不会收集子进程的CPU使用时间

但某些其他实现收集子进程CPU使用时间

clock()是C/C++中的计时函数,而与其相关的数据类型是clock_t。

它的具体功能是返回处理器调用某个进程或函数所花费的时间。函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,其中clock_t是用来保存时间的数据类型。

在time.h文件中,我们可以找到对它的定义:

#ifndef _CLOCK_T_DEFINED  

typedef long clock_t;  

#define _CLOCK_T_DEFINED  

#endif  

clock_t其实就是long,即长整形。该函数返回值是硬件滴答数,要换算成秒或者毫秒,需要除以CLK_TCK或者 CLK_TCK CLOCKS_PER_SEC。比如,在VC++6.0下,这两个量的值都是1000,这表示硬件滴答1000下是1秒,因此要计算一个进程的时间,用clock()除以1000即可。

clock的返回值一直是0的原因:

1、编译器优化,for循环实际根本没执行,直接跳过去了,所以时间为0。

2、clock计算的是程序占用cpu的时间,如果你的程序执行的动作很少,那么clock算出的时间也很少。

3、建议使用time gettimeofday函数来计时。

扩展资料:

C语言中clock()函数的程序例1:(TC下运行通过)

#include 

#include 

int main(void)

{

clock_t start, end;

start = clock();

delay(2023);

end = clock();

printf(“The time was: %f\n”, (double)(end – start) / CLK_TCK);

return 0;

}

说明:CLK_TCK 定义在TC中的time.h中:#define CLK_TCK18.2。

在VC6.0中也有关于CLK_TCK的宏定义,不过其值不再是18.2,而是1000。

实际上在VC6.0中CLK_TCK已完全等同CLOCKS_PER_SEC。

参考资料来源:

百度百科-clock()

C语言函数clock()  功 能:

返回处理器调用某个进程或函数所花费的时间。

  用 法: clock_t clock(void);

  说明:clock_t其实就是long,即长整形。该函数返回值是硬件滴答数,要换算成秒或者毫秒,需要除以CLK_TCK或者 CLK_TCK

CLOCKS_PER_SEC。比如,在VC++6.0下,这两个量的值都是1000,这表示硬件滴答1000下是1秒,因此要计算一个进程的时间,用clock()除以1000即可。具体见之一个例子。

  程序例1:(TC下运行通过)

  #include 

  #include 

  int main(void)

  {

  clock_t start, end;

  start = clock();

  delay(2023);

  end = clock();

  printf(“The time was: %f\n”, (double)(end – start) / CLK_TCK);

  return 0;

  }

  CLK_TCK 定义在TC中的time.h中:#define CLK_TCK

18.2。在VC6.0中也有关于CLK_TCK的宏定义,不过其值不再是18.2,而是1000。实际上在VC6.0中CLK_TCK已完全等同于CLOCKS_PER_SEC。

  在VC中delay用Sleep()来代替,其头文件是windows.h。

  程序例2:(VC6.0下运行通过)

  #include 

  #include 

  #include

  int main(void)

  {

  clock_t start, end;

  start = clock();

  Sleep(2023);

  end = clock();

  printf(“The time was: %d\n”, (end – start) /

CLK_TCK);//注意是%d,不再是%f

  return 0;

  }

  程序例3:(VC6.0下运行通过)

  #include “stdio.h”

  #include “stdlib.h”

  #include “time.h”

  int main( void )

  {

  long i =L;

  clock_t start, finish;

  double duration;

  

  printf( “Time to do %ld empty loops is “, i );

  start = clock();

  while( i– ) ;

  finish = clock();

  duration = (double)(finish – start) / CLK_TCK;

//CLK_TCK在VC6.0中可以用CLOCKS_PER_SEC

  printf( “%f seconds\n”, duration );

  system(“pause”);

  return 0;

  }

clock 计算的是从程序运行到执行clock时的时间间隔。

重复启动程序,时间还是 从程序运行到执行clock时的时间间隔。

这个数字不变,种子不变。你的随机就不随机了。

所以要用:

srand(time(NULL));

time(NULL) 是永远在变的。种子变,随机了。

网上资料错了,clock返回当前进程创建到现在经过的时钟周期数

你的程序那么短,返回0是正常的

我在自己的电脑上试了试,在调用clock()前用了Sleep(1000),结果就不一样了

Sleep()是 Windows API,不要在你的程序里用

而且觉得,随机数钟子只要设一次就够了,不应该每次设,

你这样,在一段时间内(大约1毫秒)都会得到同样的随机数

clock返回的大约是毫秒级(不是处理器周期,你可以查CLOCKS_PER_SEC)

使用/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就会返回特别慢,并且返回的字节数也比要求的少,甚至不返回――阻塞。我们把用户登陆处理函数放在了线程池里,导致的问题就是线程池里所有线程都可能会阻塞,这就造成了拒绝服务攻击。导致其他用户登陆失败。

解决方案:

CODE:1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7 #include

8 #include

9 #include

11 static int get_random_fd (void)

12 {

13 static int fd = -2;

15 if (fd == -2)

16 {

17 fd = open (“/dev/random”, O_RDON | O_NONBLOCK);

18 if (fd == -1)

19 fd = open (“/dev/urandom”, O_RDON | O_NONBLOCK);

20 }

22 return fd;

23 }

25 /*

26 * Generate a series of random bytes. Use /dev/random if possible,

27 * and if not, use /dev/urandom.

28 */

29 void get_random_bytes(void* buf, int nbytes)

30 {

31 int i, fd = get_random_fd();

32 int lose_counter = 0;

33 char *cp = (char*)buf;

34 struct timeval tv;

35 static unsigned seed = 0;

37 if (fd >= 0)

38 {

39 while (nbytes > 0)

40 {

41 i = read (fd, cp, nbytes);

42 if ((i

#include

#include

#include

#include

/* Return a random integer between MIN and MAX, inclusive. Obtain

randomness from /dev/random. */

int random_number (int min, int max)

{

    /* Store a file descriptor opened to /dev/random in a static

    variable. That way, we don’t need to open the file every time

    this function is called. */

    static int dev_random_fd = -1;

    char* next_random_byte;

    int bytes_to_read;

    unsigned random_value;

    /* Make sure MAX is greater than MIN. */

    assert (max > min);

    /* If this is the first time this function is called, open a file

    descriptor to /dev/random. */

    if (dev_random_fd == -1) {

dev_random_fd = open (“/dev/random”, O_RDON);

assert (dev_random_fd != -1);

    }

    /* Read enough random bytes to fill an integer variable. */

    next_random_byte = (char*) &random_value;

    bytes_to_read = sizeof (random_value);

    /* Loop until we’ve read enough bytes. Because /dev/random is filled

    from user-generated actions, the read may block and may only

    return a single random byte at a time. */

    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);

    /* Compute a random number in the correct range. */

    return min + (random_value % (max – min + 1));

}

关于linux 熵池的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » Linux系统中的熵池机制及其作用简介 (linux 熵池)