Version 4 of Cryptographically secure random numbers using /dev/urandom

Updated 2011-12-23 04:10:23 by bodangly

Cryptographically secure random numbers are difficult to achieve, but important for things such as password and session key generation. You probably want a strong random number generator for something such as casino games involving real money. There are some solutions available in Tcl already, particularly in the Random package which provides a C implementation of the ISAAC algorithm. ISAAC is considered a cryptographically secure algorithm. Tcllib provides the rc4 package, a stream cipher that is essentially a random number generator. However, if you are in a recent Linux environment chances are your kernel has support for /dev/random and its counterpart /dev/urandom. These kernel modules poll drivers and the running system to collect entropy used in generating true random numbers. The only difference between /dev/random and /dev/urandom is that /dev/urandom will start generating numbers with repeating entropy once the buffer has been overrun, as random is blocked and urandom is not. So for something such as a long-term cryptographic key it is usually recommended to generate using /dev/random, however, urandom is still considered a cryptographically secure pseudo-random number generator. For times when you need to generate random numbers often, /dev/urandom is more convenient than /dev/random. If you want a "truly" random number though, use /dev/random. The only other "true" random numbers available to most Tcl applications would be random.org, and relying on a third-party that transmits your numbers in the clear kind of defeats the purpose of a secure RNG. So, lets take advantage of these powerful, mature tools that Linux offers us. Below is an example of a function to generate a random unsigned integer up to 64 bits using /dev/urandom.

proc randInt { min max } {
    set rand [open {/dev/urandom}]
    set random [read $rand 8 ]
    binary scan $random H16 random
    set random [expr (0x$random % $max) + $min]
    set random [expr $random > $max ? ($random % $max) + $min  : $random]
    close $rand
    return $random
}