(SEED-Lab) 伪随机数生成实验
欢迎大家访问我的GitHub博客
https://lunan0320.cn
文章目录
- (SEED-Lab) 伪随机数生成实验
- 一、实验目的
- 二、实验步骤与结果
-
- Lab Tasks
-
- Task 1: Generate Encryption Key in a Wrong Way
- Task 2: Guessing the Key
- Task 3: Measure the Entropy of Kernel
- Task 4: Get Pseudo Random Numbers from /dev/random
-
- **Question:**
- Task 5: Get Random Numbers from /dev/urandom
一、实验目的
1.熟悉伪随机数的生成
3.了解常见的伪随机数生成中的错误
4.掌握生成用于安全目的的伪随机数的标准方法
5.掌握如何生成安全的加密密钥
二、实验步骤与结果
Lab Tasks
Task 1: Generate Encryption Key in a Wrong Way
首先根据指导书要求,书写正确的代码。
编译后运行结果如下。
接着将srand(time(NULL))注释掉
同样编译运行,得到如下结果。
但是,发现这样并不能比较二者的优劣,尝试多次运行后,发现了不同。
可以看到,在使用了srand(time(NULL))命令后,每次得到的随机密钥都是不同的。打印出来的time值其实也是不同的。
但是,注释掉之后,发现虽然每次的time值是不同的,但是每次运行出来的随机数key已经是不同的了。
代码中srand()函数是生成一个随机的种子,在使用rand()函数的时候是基于该随机种子进行的。但是如果没有srand()函数的随机种子,每次的随机数是使用的系统默认的种子,这样产生的随机数就是相同的。
代码中time()函数是获取系统从1970年1月1日0:0:0开始到现在的秒数。因此,这个值在每次程序的执行过程中都是会变化的。
Task 2: Guessing the Key
首先需要获取的是从1970.1.1 0:0:0开始到目标时间2018-04-17 23:08:49的秒数。
又因为文件是在此之前的两个小时内加密的,因此还需要知道在这之前的两小时之前的秒数。1524013729
得到了时间之后就相当于可以通过srand()函数来知道种子,又知道密钥的生成是通过Task1中的程序生成的,因此可以仿照Task1中的程序去求出这两小时窗口内的密钥。
这样,得到的就是这两小时的密钥的可能值(十六进制)。
此时需要用代码去遍历这两小时的可能值。根据在实验六中的Task3的遍历方法即可。
这里沿用了实验六的代码,区别是这里的明密文以及密钥都是16bytes的,因此不需要通过#PKCS7去填充了,直接加密即可。
注意:此处因为给出的是十六进制的值,因此,还需要考虑的是将其转换为使用的bytes类型。这也是我长时间没有找出密钥的原因。
查阅资料后,了解到python中使用bytes以及hex的转换方法。
我在这里是使用的bytes.fromhex()将hex转换为bytes。使用bytes().hex()将bytes转换为hex类型。如下。
找到密钥后,退出循环即可。
这里展示的是在Pycharm中得出的结果。因为是遍历文本去验证的操作,速度还是很快的。
Task 3: Measure the Entropy of Kernel
这个任务是想让直观地感受一下熵的效果。
在这里我是先去查看了当前kernel中的entropy,即系统当前所拥有的随机数的比特数。
观察后发现,当我多次运行该命令查看的时候,这个数值是在发生变化的,因为我的每一次输入都会有移动鼠标,键盘输入等活动,这就是一个增加熵的过程。因此,每次打开之后数值必然是增大的。
接着,我测试了在全屏模式下对熵的测量变化情况。
在这个过程中,我打开了一个大的文件,就是Task2中的keys.txt文档,并在其中任意一行随便输入了一些数值,作为了键盘的输入,在此期间也多次随意移动鼠标。
观察:在这个过程中,我一直在观察这个全屏模式下的数值的大小,通过我的一系列动作,其数值在不断增大。从刚刚截图中的791到达了2459的数值量。当我输入的速度较快,或者鼠标随意移动的速度较快的时候,数值的增加是越明显的。
Task 4: Get Pseudo Random Numbers from /dev/random
此处是测试/dev/random的random pool。
当我在一个terminal中运行使得以hex形式dump,在另一个terminal中通过watch命令去观察这个数值。发现都是在一直降低,当降低到一定数值后,就不能再降低了。
然后当我再次移动鼠标,数值又会增加,增加到一定数值后,就以hex模式输出,数值就会又降到很低。
Question:
If a server uses /dev/random to generate the random session key with a client. Please describe how you can launch a Denial-Of-Service (DOS) attack on such a server
对于需要为client生成随机会话密钥的Server,可以对它的Server一直发起此类攻击,使得random pool的熵几乎没有,这样随机数的生成基本也就停止了,也就无法继续为Client服务了,成功发起了DDOS攻击。
Task 5: Get Random Numbers from /dev/urandom
运行cat /dev/urandom | hexdump 命令。查看当前的urandom随机数。
观察后发现,在运行该命令的时候,随机数是源源不断地打印出来,即使鼠标停止不动,或者鼠标移动,都没有影响。随机数的生成不会因此而停止。
此时需要生成1M的随机数到文件中,并分析随机数的质量。
可以看到,随机数的熵达到了7.999844bits/bytes,一个字节8bit的情况下,这个数值已经很高了。
卡方分布是227.02,随机数超过该值的概率是89.57%,也是较高的。
蒙特卡洛值计算的PI,误差仅仅只有0.01%,也是很小的。
序列的相关度达到了0.000760,总体相关度为0。这能说明序列是相当随机的。
综上:生成的随机数的质量是很高的。
修改代码,使之打印除256位的随机数。
其中,需要在样本代码的基础上添加打印代码的部分,切密钥长度改为256bit,也就是32bytes
执行此程序,多次执行,查看结果的不同。
发现,此时打印出的32bytes的随机数,每次的执行效果也是不同的,这样就可以通过/dev/urandom获得真的随机数。
同时,这个过程并没有发生拒绝服务,每次生成随机数之间差别也是很大,随机数的质量也很高。