Arduino Random Number Generator

Inspired by other designs I've seen online, most directly Rob Seward's design, I decided to build my own random number generator based Will Ware's "avalanche noise in a reverse-biased PN junction" (try this mirror of Will Ware's page)

I also read about the ORB Random Bit Generator which mostly reminded me to consider the low-order bits of the ADC reading.

My circuit uses a MAX680 to produce ∼±10V so that I have the requisite 18V across the PN junction. At $4 (qty 1) you may be better off choosing a MAX232-type chip and ignoring the receive/transmit functionality.

Originally I used the LSBs of the ADC, following the lead of Seward by using ADC, and the insight of the ORB project to use LSBs rather than MSBs. This led to low data rates (as low as 1KB/s), so instead I decided to use the amplified noise as a digital input. Digital inputs can be sampled at a much higher rate, so even if more samples are required to get a random output byte, the data rate can be higher.

The digital noise is both biased and correlated. In order to whiten the digital noise, 64 bits are mixed into a 16-bit register pair using a construct related to a LFSR, so that each bit of noise eventually influences each bit in the register, and 4x more noise bits are input than "random" bits are output. There's no proof of the degree of entropy in each bit of output, but the output from the arduino serial port passes the dieharder testsuite while giving a rate of over 50KiB/s.

The package includes a program to read random numbers (rr), and one to add random numbers to the linux /dev/random entropy pool (rd). These programs are written in Python and require pyserial (Ubuntu package name: python-serial).

Because of the baud rate used (2Mbps), Linux users will require pyserial 2.3 or above.

For more details, see the README and source code included in the zip file.

The astute eye will notice that there's a resistor in the board photo which is not present in the design files. This reflects an earlier revision of the circuit, in which ANALOG0 had a resistive divider R3:R4 as in Seward's design (but value 4.7k in both cases). R4 pulled the voltage down so low that it never reached the minimum voltage to provide a "1" input. I clipped it on my board and removed it from the design files.

There's also a peculiarity on the Arduino board: this is a very old board with no auto switching between USB and external power sources for the logic supply. the diode-on-tiny-circuit-board is my rudimentary attempt at adding this feature. It doesn't affect the functioning of the RNG.

Update, June 2011: Added a prose description of the LFSR whitening algorithm.

Update, January 2012: I'm in the process of running a DieHarder (3.31.1) suite on the device to see whether aging has affected its output. Rob Seward had mentioned that his initial design without self-calibration would become non-random after about 3 months, possibly due to component aging. The test (with 4x psamples and -Y1 to repeat any test that is deemed WEAK) isn't complete yet, but with 219GiB of random data read (about 24 days at 112KiB/s) every test so far has PASSED. This seems to indicate that my design of an LFSR whitener and a 4:1 ratio of input "noise" bits to output "random" bits is adequate.

Files currently attached to this page:

rng.zip49.5kB



Entry first conceived on 10 November 2009, 16:00 UTC, last modified on 27 January 2012, 19:34 UTC
Website Copyright © 2004-2012 Jeff Epler