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

Updated 2011-12-24 00:53:36 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 pseudo-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 { max } {
    set rand [open /dev/urandom BINARY]
    set random [read $rand 8 ]
    binary scan $random H16 random
    set random [expr (0x$random % ($max+1)) ]
    close $rand
    return $random
}

RLE (2011-12-23): Changed open above to open /dev/urandom in BINARY mode. /dev/urandom returns random binary data and reading from the channel in cooked mode would slightly reduce the available entropy.