密码学都会涉及到随机数,因为许多密码系统的安全性依赖于随机数的生成。
序列密码的保密性完全取决于密钥的随机性。如果密钥是真正的随机数,那么这种体制理论上就是不可破译的。但这种方式所需要的密钥量大的惊人,实际中是不可行的。
目前一般采用伪随机序列来代替随机序列,也就是密钥存在的一定的循环周期。这样循环周期的长短就成了保密的关键,如果周期足够长,就会有比较好的保密性。一般周期小于10^10的序列很少被采用。
下面这段程序,完整地阐述了计算机随机数产生的过程。
#include <stdlib.h>
static unsigned int RAND_SEED;
unsigned int random(void)
{
RAND_SEED=(RAND_SEED*123+59)%65536;
return(RAND_SEED);
}
void random_start(void)
{
int temp[2];
movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);
RAND_SEED=temp[0];
}
main()
{
unsigned int i,n;
random_start();
for(i=0;i<10;i++)
printf("%u\t",random());
printf("\n");
}
主函数中首先调用了random_start函数,里面的一句movedata(0x0040,0x006c,FP_SEG(temp),FP_OFF(temp),4);是程序的重点。movedata用 法:
void movedata(int segsrc, int offsrc, int segdest,int offdest, unsigned numbytes);
可见,temp数组中内容的改变是和0040:006c地址有关。而该地址与定时/计数器有关。所以随机数种子来源于系统时钟。
何谓伪随机数生成器(PRNG)?假定要生成介于1~10之间的随机数,每个数出现的概率是一样的。理想情况下,应生成0~1之间的一个值,不考虑以前值,这个范围中每个值出现的概率是一样的,然后再将该值乘以10。
由任何伪随机数生成器返回的数目都会受到0到N之间整数数目的限制。因为常见情况下,伪随机数生成器生成0到N之间的一个整数,返回的整数再除以N。可以得到的数字总是处于0到1之间。对生成器随后的调用采用第一次运行产生的整数,并将它传给一个函数,以生成0到N之间的一个新整数,然后将新整数除以N返回。
伪随机数生成器将作为“种子”的数当做初始整数传给函数,由伪随机数生成器返回的每一个值完全由他前一个返回的值决定。因此最初的种子决定了整个随机数序列。如果知道用于计算任何一个值的那个整数,那么可以算出从这个生成器返回的下一个值。
伪随机数生成器是一个生成完全可预料的数列(称为流)的确定性程序。一个编写的很好的PRNG可以创建一个接近真随机数序列的数列。而好的PRNG特征如,可以以相同几率在一个范围内生成任何数字,可以生成带任何统计分布的流,生成的数字流不具备可辨别的膜模。
基于密码算法的随机数产生器:
使用软件方法的随机数产生器
一个常用的随机数产生器是属于线性拟合生成器一类的。这类生成器相当普遍,他们采用很具体的数学公式:即第N+1个数是通过第N个数经过一定线性变换再通过模c把它限制在0~c之间。(注意,a、b、c通常都是质数,模C是质数是为了更好地散射分布)硬件方法生成,不讨论
伪随机数的评价标准:
- 可以通过所有随机性统计检验
- 不可预测
- 不能可靠地重复产生