# lab_Pseudo_Random_Number ###### tags: `linux`, `random number` ## Environment ``` x86_64 Ubuntu 20.04.5 LTS ``` ``` x86_64 Ubuntu 16.04.7 ``` </br> </br> </br> ## TASK 1: Generate Encryption Key in a Wrong Way ```c= #include <stdio.h> #include <stdlib.h> #include <time.h> #define KEYSIZE 16 int 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"); return 0; } ``` ``` # result 1665937533 c066f685a89a03e3ee38701c026b7f4 # result 2 1665937533 ac066f685a89a03e3ee38701c026b7f4 # result 3 1665937534 116284de93498bd7a041fd0fef3a1dcc ``` At first glance, we can notice that the `result 1` and `result 2` was the very same. So we can assume that it is caused by the fact that they were executed in "same" time. Accroding to the man page: > The srand() function sets its argument as the seed for a new sequence of pseudo-random integers to be returned by rand(). These sequences are repeatable by calling srand() with the same seed value > [name=man page] we can know that the purpose of line:13 `srand(time(NULL))` is to use time as the seed of `rand()` function. </br> </br> ## Task 2: Guessing the Key 1. Calculate the date. ```bash ❯ date -d '2018-04-18 23:08:49' +%s # the date i used in code 1524034800 ❯ date -d '2018-04-17 23:08:49' +%s # the date in pdf 1523977729 ❯ date -d "2018-04-15 15:00:00" +%s 1523775600 ``` :::warning Note: Because the time zone difference between me and the where the pdf comes from, I use '2018-04-18' instead of '2018-04-17' in the pdf ::: </br> 2. Install openssl package ```bash sudo apt install libssl-dev ``` </br> 3. Decrypt the cipher with AES CBC 128bits ```c void decrypt(unsigned char *cipher, unsigned char *key, unsigned char *iv, unsigned char *result) { AES_KEY ctx; unsigned char tmp_iv[16] = {0}; memcpy(tmp_iv, iv, 16); AES_set_decrypt_key(key, 128, &ctx); AES_cbc_encrypt(cipher, result, 16, &ctx, tmp_iv, AES_DECRYPT); } ``` 4. Try generate the key in all possible time, then choose the right one ```c for (unsigned long seed = TIME_LOWER_LIMIT; seed <= TIME_UPPER_LIMIT; seed++) { gen_key(seed, key); // from task1.c unsigned char tmp_plain[16] = {0}; decrypt(cipher, key, iv, tmp_plain); if (memcmp(plain, tmp_plain, DATA_SIZE) == 0) { print_hex(key, KEYSIZE); return 0; } } ``` </br> </br> ## Task 3: Measure the Entropy of Kernel ```bash $ watch -n .1 cat /proc/sys/kernel/random/entropy_avail ``` I use a VM to emulate early version of linux to lab this secion, because the latter version of linux changed this "harvest hardware randomness" feature. ### In Ubuntu-16 / kernel version: 4.15.0-112-generic while moveing mouse around: 2890 ~ 3017 while opening firfox: 3540 while creating a large file: 3840 > btw the "create a large file" experience broke my VM > ![](https://i.imgur.com/DnsCgSK.png =x400) > I used the `yes > a` command to create large file Then I notice that the entropy will decrease overtime. ### After 5.10.119 After linux 5.10.119 the value of `/proc/sys/kernel/random/entropy)avail` is always 256. It's not a bug, it's a new feature to the new version of linux kernel. ### Disscuss input_pool.entropy_count </br> </br> ## Task 4: Get Pseudo Random Numbers from /dev/random ![](https://i.imgur.com/hlCRAH7.png) blocking :::warning **Question:** > If a server uses `/dev/random` to generate the random session key with a client. Please describe how you can launch a DOS attack on such a server. You can try to request a lot of secure connection, to force the server to generate a lot of keys and run out server's entropy pool ::: ### After linux 5.10 `/dev/random` and `/dev/urandom` almost same ==todo== </br> </br> ## Task 5: Get Random Numbers from /dev/urandom ![](https://i.imgur.com/2o0PB5T.png) unblock > [ent man from ubuntu](https://manpages.ubuntu.com/manpages/xenial/man1/ent.1.html) ![](https://i.imgur.com/r99yQPM.png)