[seed-labs] 伪随机数生成器

[seed-labs] 伪随机数生成器

实验目的

  • 了解伪随机数生成算法及其相关概念
  • 通过案例了解伪随机数生成过程中的漏洞
  • 掌握安全生成伪随机数的方法
  • 了解如何安全地生成加密密钥

实验过程

Task 1: 用错误的方式生成加密密钥

  • 使用当前时间作为伪随机数生成器的种子

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define KEYSIZE 16
    
    void main()
    {
    	int i;
    	char key[KEYSIZE];
    
    	printf("%lld\n", (long long) time(NULL));
    	srand (time(NULL)); //➀
    
    	for (i = 0; i< KEYSIZE; i++){
    	key[i] = rand()%256;
    	printf("%.2x", (unsigned char)key[i]);
    	}
    	printf("\n");
    }
    
  • 结果

    image-20221210201556385

  • 根据观察结果和查找资料我们可以得到:

    • 代码中srand()函数通过time()得到一个种子,在使用rand()函数生成该随机数时是根据种子进行的,如果没有srand()函数则产生的随机数相同,即:
      • time()srand(time())是随机的
      • rand()是伪随机的
      • srand(seed)用于给rand()设定种子

Task 2: 猜测密钥

  • 首先分析加密密钥为该程序生成,那么该密钥一定与时间戳有关,我们先得到加密文件创建的前两个小时的所有秒数,time()的范围一定在计算机可测时间范围内,求出密钥空间

    image-20221210204120412

    根据第一题改变代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    #define KEYSIZE 16
    
    void main()
    {
    	int i;
    	long long t;
    	char key[KEYSIZE];
    
    	//printf("%lld\n", (long long) time(NULL));
    	//srand (time(NULL)); //
    
    	for (t=1524013729;t<1524020929;t++){
    		srand(t);
    		for(i=0;i<KEYSIZE;i++){
    			key[i] = rand()%256;
    			printf("%.2x", (unsigned char)key[i]);
    		}
    		printf("\n");
    	}
    	printf("\n");
    }
    
  • 密钥生成

    from Crypto.Cipher import AES
    
    data = bytearray.fromhex('255044462d312e350a25d0d4c5d80a34')
    ciphertext = bytearray.fromhex('d06bf9d0dab8e8ef880660d2af65aa82')
    iv = bytearray.fromhex('09080706050403020100A2B2C2D2E2F2')
    
    with open('C:/Users/Laotie666/Desktop/key.txt') as f:
        keys = f.readlines()
    
    for k in keys:
        k = k.rstrip('\n')
        key = bytearray.fromhex(k)
        cipher = AES.new(key=key, mode=AES.MODE_CBC, iv=iv)
        guess = cipher.encrypt(data)
        if guess == ciphertext:
            print("the key is : ", k)
            break
    

    image-20221210213003866

Task 3: 测量内核的熵

  • 测量kernel的熵

    image-20221210213935306

    image-20221210213847303

  • 发现打开大文件然后写入时增加熵较快,大概一下+10左右,鼠标点击一下+5左右,当然这些也是大概估计,他的值一直是动态的非线性不可预测时间间隔下变化的

Task 4: 从 /dev/random 中获取伪随机数

  • 从/dev/random中获取伪随机数。请运行给出的命令,同时使用watch命令来监测熵。
  • image-20221210214814215
  • 我发现如果不移动鼠标或者不输入内容,观测到的熵会逐渐的增加,每次增加1-2左右(频率也不固定),然后每两次增加到63时,随机数池会多生成一行;同时每次增加到63时,观测到的熵会从0开始
  • 对于需要为client生成随机会话密钥的Server,可以对它的Server一直发起此类攻击,使得random pool的熵被耗尽,这样随机数的生成基本也就停止了,也就无法继续为Client服务了,成功发起了DDOS攻击。

Task 5: 从 /dev/urandom 获取随机数

  • Linux 提供了另一种方式,可以通过 /dev/urandom 设备访问随机池。

  • /dev/random 和 /dev/urandom 都可以使用随机池中的数据生成伪随机数。当熵不足时,/dev/random 将会暂停,而 /dev/urandom 会继续生成新的数。将随机池中的数据视作“种子”,我们可以使用种子想生成多少随机数就生成多少。

  • 再次使用cat从设备中获取伪随机数

     cat /dev/urandom | hexdump
    

    答案是不会,会连续生成很多的随机数,完全够用

  • 生成并测试质量

    head -c 1M /dev/urandom > output.bin
    ent output.bin
    

    image-20221210220551978

    结论是质量很高

  • 下列代码实现使用/dev/random获取随机数

    #include <stdio.h>
    #include <stdlib.h>
    
    #define LEN 32 // 32*8 bits
    
    int main(){
      unsigned char * key = (unsigned char *)malloc(sizeof(unsigned char) * LEN);
      FILE * random = fopen("/dev/urandom", "r");
      int i;
      fread(key, sizeof(unsigned char) * LEN, 1, random);
      fclose(random);
      printf("the key is : ");
      for (i=0; i<LEN; i++){
        printf("%.2x", key[i]);
      }
      printf("\n");
      return 0;
    }	
    

    image-20221210221352468

篇外

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值