Geek Rant

All talk and no action

More Computer Random vs. True Random

leave a comment »

A little while ago in #haskell on Freenode, one topic of discussion was random number generators. I wasn’t at my computer at the time, but when I came back, dejones had linked to a blog post about the patterns of pseudo random number generators. The author had made a PHP script which generates a random image using PHP’s rand function and compares it to one generated with true random numbers. The difference is significant.

dejones complained that there was no image for /dev/random on Linux, and I was curious about Haskell’s built-in random number generator, so I wrote a Haskell program to do the same thing and ran it on Linux. (As I type this, I am still gathering entropy for the /dev/random run. Just a warning, it’s still not done. I will be updating this some time tomorrow with the final image.)

Update: I never did gather enough entropy. I allowed the computer to run over 24 hours while I did all kinds of perverse things to the hard drive (old one, wouldn’t be devastating to lose it anyway), and still couldn’t gather enough entropy to generate the image. Perhaps I would fare better if I altered the program to use every single bit from /dev/random instead of just using modulo two of each character.

My original program tested Haskell’s random number generator. It looks like this:

module Main where

import Control.Monad
import qualified Graphics.GD as GD
import System.Random

imageSize = (512, 512)

imagePoints = do x <- [0..(fst imageSize - 1)]
                 y <- [0..(snd imageSize - 1)]
                 return (x, y)

main = do image <- GD.newImage imageSize
          plots <- randoms `liftM` getStdGen
          sequence_ $ zipWith (plot image) imagePoints plots
          GD.savePngFile "out.png" image
    where plot i p True = GD.setPixel p (GD.rgb 255 255 255) i
          plot i p False = GD.setPixel p (GD.rgb 0 0 0) i

I’m using the GD library to create a PNG image. I won’t bother explaining the code for this.

And here is what that creates:

So not too bad. Now let’s try Linux’s /dev/urandom:

module Main where

import Control.Monad
import qualified Graphics.GD as GD
import System.IO

imageSize = (512, 512)

imagePoints = do x <- [0..(fst imageSize - 1)]
                 y <- [0..(snd imageSize - 1)]
                 return (x, y)

main = do image <- GD.newImage imageSize
          devfile <- openFile "/dev/urandom" ReadMode
          hSetBuffering devfile NoBuffering
          plots <- fmap ((==0) . (`mod` 2) . fromEnum) `liftM` hGetContents devfile
          sequence_ $ zipWith (plot image) imagePoints plots
          GD.savePngFile "out.png" image
    where plot i p True = GD.setPixel p (GD.rgb 255 255 255) i
          plot i p False = GD.setPixel p (GD.rgb 0 0 0) i

And here is what it looks like:

This looks pretty similar to the output of Haskell’s generator, to me, but if somebody sees something I don’t then please do tell.

The code for /dev/random is exactly like the code for /dev/urandom, except we, obviously, use /dev/random instead! I would post the output image here now, but I can’t seem to gather enough entropy yet. I have to go home now. I’ll just post the image some time tomorrow. Sorry about that!

Update: As I mentioned in the update above, I never did get this done. I will get around to it eventually.

Written by Jake

May 20, 2008 at 9:36 pm

Posted in Uncategorized

Leave a Reply