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

Updated 2011-12-24 13:47:31 by RLE

Cryptographically secure random numbers are important any time your random numbers are being used in what is meant to be a secure application; for example when generating passwords and cryptographic keys. Tcl's rand is not cryptographically secure. However, Tcllib does offer rc4, a stream cipher that is at its core a pseudo-random number generator. There is also the Random package which uses the ISAAC algorithm; which is considered secure.

These aren't bad solutions, but if you are in a modern Linux based environment your kernel should have support for /dev/random and /dev/urandom. The /dev/random kernel module polls the running system to gather entropy used to generate what are considered true random numbers. The only other true random numbers available to most Tcl applications is random.org, however this service transmits your numbers in the clear which in most instances requiring security is unacceptable.

/dev/random is powerful and mature, and so it only makes sense to take advantage of when available. The counterpart to /dev/random is /dev/urandom, which stands for "unblocked" random. /dev/random is "blocked" meaning when the pool of available entropy is exhausted you must wait until additional entropy is gathered to get new random data. /dev/urandom does not block, and instead will reuse the entropy pool. While this decreases the quality of the randomness over time, it is still considered a cryptographically secure PRNG. What follows is the example of a function that can generate a 64 bit unsigned integer within a range, using /dev/urandom. Note that /dev/random and /dev/urandom are simply treated as files.

proc randInt { min max } {
    set randDev [open {/dev/urandom} rb]
    set random [read $randDev 8]
    binary scan $random H16 random
    set random [expr (0x$random % (($max-$min) + 1) + $min)]
    close $randDev
    return $random
}

RLE - 2011-12-23 19:55:58 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.


bodangly - 2011-12-23 19:55:58

Good catch RLE, I noticed a slight irregularity in the distribution previously and was trying to figure it out. BINARY told me it required permissions to be set so I changed the above code to use "rb" instead. Edit: Whoops. =\ Wiped out the page, led me to rewrite things a bit more succinctly and update the function to accept both a min and max.

nem 2011-12-24: Won't the use of % (mod) also skew the distribution?

RLE (2011-12-24): Try it with "[open /dev/urandom {RDONLY BINARY}]". I left out the "RDONLY" in my last edit. Note also that there is no need to brace quote the constant filename unless the filename contains spaces or characters that are special to the Tcl parser. The name "/dev/urandom" contains nothing special and no spaces.