This library https://bitbucket.org/mike1452/msprandom demonstrates a technique which allows to solve the problem of getting random numbers on computers and small devices for cryptographic purposes. So, if you need encrypt and sign data on a small device or computer without hardware RNG do the following:
- Create true random numbers vault using this library on your computer or notebook.
- Put this vault on your device, computer or server where you need encrypt and sign data.
- Load the vault once at the start of the program when you need encrypt or sign data.
- Call secure-rand function to get random bytes as many times as you need.
Vault is encrypted and secured with HMAC. Random data in a vault is updated every time you load random seed with unpredictable way, so HMAC is recalculated too.
Gathering a true random data
To get a true random data a human input is used. Algorithm of collecting a random data:
- Run separate thread where atomic counter increments every tic from 0..255 with a very high speed.
- Wait for unbuffered key press by human and get a scan code of pressed button.
- Take current nanoseconds value from start of Epoch and take mod 256 to convert its value to a random byte.
- Xor values between each other: scan-code-byte ^ current-counter-value ^ nanoseconds to produce random byte.
- Add random byte to output vector. We suppose that only 3 bits has true randomness in this random byte. So, to get true random 32 bytes we need ~ 32*3 button press from user input. 6 Repeat steps 2-5 until we get required amount of random bytes.
- If we collected required amount of random data then do final step -> hash output vector with cryptographically strong hash function GOST 3411-94 to guarantee that probability 1 and 0 bits in output vector will be 0.5. Note, that hash function used here only to mix random bits and do not influence to the quality of random data. So hash(random data) = random data. Hash will produce vector of 32 bytes containing a random data.
- Repeat steps 1..7 if we need more than 32 bytes of random data.
Using this algorithm we collect a true 512 random bits. Why 512? Well, every PRNG needs a true random seed. If an attacker knows a seed then you can't protect your data. 256 bit length is far enough to keep millitary grade secrets. I did 512 to close the security question of random seed. My opinion, 512 bit of true random data is enough to use in PRNG: generating keys, signatures, etc.