The initial pseudo-random seed is taken from the current time. The first pseudo-random number in the sequence comes from the SHA-256 hash of the initial seed + the number 0, the second pseudo-random number comes from the hash of the initial seed + the number 1 and so on. To get an output of certain range [min...max] the 256-bit hash is divided to (max - min + 1) and min is added to it. The number i, together with the value startSeed hold the internal state of the random generator, which changes for each next random number.

The above pseudo-random generator is based on the random statistical distribution of the SHA-256 function. It is expected that the chance for each possible number to be generated is equal.

Creating a Secure Random Generator

The above random generator is not secure, because it is not initialized by an unpredictable source of entropy. Let's fix this.

We shall initialize the initial randomness based on the keyboard events. The user will be asked to enter something 5 times and the exact precise times of the moments of the user input, together with the data entered from the user will be joined as initial randomness (seed). The collected text entropy can be shortened through SHA-256 hashing (this will reduce it to 256 bits). After the entropy is collected and the start seed is calculated, the same logic like at the previous example will be used to generate 5 random numbers in the range [10...20]. This is a sample Python implementation:

Note that the collected entropy is very hard to be predicted. The cracker should guess all the text entered by the user and also guess the exact time for each of the 5 inputs. If the above is repeated 20 instead of 5 times, it will be even harder to predict (the collected entropy will be bigger).

Some cryptographical software use similar techniques like in the above code example when generating keys, password and randomness as general and now you know why: to collect entropy in an unpredictable way.