openssl中随机数产生的原理

概述

  1. 第一步用RAND_poll()初始化MD_DIGEST_LENGTH长度的全局变量md。
    1.1 初始化过程用读取/dev/urandom /dev/urandom等方式读取原始的32字节,以RAND_add的方式将结果存入全局数组md。(UNIX的实现过程)
    1.2 然后RAND_add上pid、uid、time等数据。
  2. RAND_add “…”
  3. 计算pid、time、FILETIME、全局数组md、md_c、全局状态数组state的哈希值。循环此过程填充输出结果的buf直到指定的num长度。
  4. 利用第3步的计算机国更新全局数组md,下一次调用此随机数将不调用第1步,而直接从第2步开始,初始化数据从本次的计算结果。
  5. RAND_add的计算方法:计算全局数组md、全局状态数组state、被Rand_add的数组、md_c的哈希值存入全局数组md。

全局变量:

#define STATE_SIZE 1023
static size_t state_num = 0, state_index = 0;
static unsigned char state[STATE_SIZE + MD_DIGEST_LENGTH];
static unsigned char md[MD_DIGEST_LENGTH];
static long md_count[2] = { 0, 0 };

公式化流程:

  1. md的初始化:
    1.1 windows
    RAND_add(buf = CryptGenRandom(),add=64);
    RAND_add(time, add=0);
    RAND_add(GlobalMemoryStatus(), add=1);
    RAND_add(CurrentProcessId, add=1);
    1.2 OPENSSL_SYS_VOS
    RAND_add(getgid(), add=1);
    RAND_add(getpid(), add=1);
    RAND_add(getuid(), add=1);
    RAND_add(clock_gettime()%256);
    1.3 OpenBSD
    RAND_add(arc4random(), 32, 32);
    1.4 !OPENSSL_SYS_VOS && !OpenBSD
    read(/dev/urandom, tmpbuf, 32);
    RAND_add(tmpbuf, add=32);
    RAND_add(getpid(), add=0);
    RAND_add(getuid(), add=0);
    RAND_add(time(NULL), add=0);

  2. 1023/20 次RAND_add("…").

  3. 3.1 local_md = md;
    3.2 更新 md_count[0] += 1;
    3.3 local_md = SHA1(getpid(), time(NULL), FILETIME, local_md, md_count[0], state[st_idx]);SHA1每次用update来加入一个随机因子。
    3.4 更新状态 state[index] ^= local_md;
    3.5 md = SHA1(md_count[0], local_md, md);

  4. rand_add(const void *buf, int num, double add):
    4.1 local_md = md;
    4.2 更新md_count[1] md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0);
    4.3 local_md = SHA1(local_md, state[st_idx], buf, md_count[0]); SHA1每次用update来加入一个随机因子。
    4.4 更新md md ^= local_md;
    4.5 如果熵值entropy不足ENTROPY_NEEDED,熵值entropy加上参数列表中的值add;

一些解释:

  1. 步骤1.1中的解释,GlobalMemoryStatus()获取包含了物理内存和虚拟内存的细节的结构体 MEMORYSTATUS
    结构成员的含义:
    dwLength   MEMORYSTATUS结构的大小,在调GlobalMemoryStatus函数前用sizeof()函数求得,用来供函数检测结构的版本。   
    dwMemoryLoad   返回一个介于0~100之间的值,用来指示当前系统内存的使用率。   
    dwTotalPhys   返回总的物理内存大小,以字节(byte)为单位。   
    dwAvailPhys   返回可用的物理内存大小,以字节(byte)为单位。   
    dwTotalPageFile 显示可以存在页面文件中的字节数。注意这个数值并不表示在页面文件在磁盘上的真实物理大小。   
    dwAvailPageFile 返回可用的页面文件大小,以字节(byte)为单位。   
    dwTotalVirtual  返回调用进程的用户模式部分的全部可用虚拟地址空间,以字节(byte)为单位。   
    dwAvailVirtual  返回调用进程的用户模式部分的实际自由可用的虚拟地址空间,以字节(byte)为单位。

windows中的md初始化用此结构体的内存作为随机因子。

你可能感兴趣的:(Algorithm,openssl)