Languages
Social Media
Feeds
Powered by Squarespace
Social

« SOPA/PIPA The end of the internet as we know it. | Main | Steve Jobs - Will be missed. »
Wednesday
Nov092011

Netduino Powered True Random Number Generator (TRNG)

In software development, most often when we want to generate a random number we have to generate a Pseudorandom Number.  However there are times when you need a true random number, weather for cryptographic purposes or for lotteries.  To generate true random numbers you need a True Random Number Generator (TRNG), which must be a piece of hardware.  There are several on the market which use a variety of methods to generate their randomness.  I used the circuit developed by Rob Seward, which uses avalanche noise between the two transistors... I'll let Rob Seward explain it in his own words.

The two transistors with their bases touching create "avalanche noise in a reverse-biased PN junction." This noise is amplified by the third transistor, and sent across a voltage divider to Arduino. On the oscilloscope, the signal looks very fuzzy. In software, that randomness is converted into a stream of 1s and 0s.

Since I love my Netduino, and I love building cool stuff, I decided to build one of these for my Netduino.

The code for it is fairly straight forward

 

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace TRNG
{
    public class Program
    {
        #region configuration
        //Configuration
        //8 Bits gives you an int output of 0-255
        //16 bits gives you an int output of 0-65535
        //32 bit gives you a stackoverflow. :)
        private static int bits = 8;
        //End Configuration
        #endregion

        #region ports
        private static OutputPort led = new OutputPort(Pins.ONBOARD_LED, false);
        private static AnalogInput in_port = new AnalogInput(Pins.GPIO_PIN_A0);
        private static OutputPort _0led = new OutputPort(Pins.GPIO_PIN_D0, false);
        private static OutputPort _1led = new OutputPort(Pins.GPIO_PIN_D1, false);
        #endregion

        #region bias removal stuff
        private static int previous;
        private static int flip_flop = 0;
        #endregion

        private static int calibration_value = 0;
        private static string byt = "";

        private static void Loop()
        {
            int d = in_port.Read();

            if (d > calibration_value)
            {
                ExclusiveOr(1);
                //byt = byt + "1";
                _0led.Write(true);
                Thread.Sleep(30);
                _0led.Write(false);
            }
            else
            {
                ExclusiveOr(0);
                //byt = byt + "0";
                _1led.Write(true);
                Thread.Sleep(30);
                _1led.Write(false);
            }

            if (byt.Length == bits)
            {
                Output();
            }
    }
        private static void Calibrate()
        {
            DateTime start = DateTime.Now;
            TimeSpan ts = DateTime.Now - start;
            int count = 0;
            int total = 0;
            //Making this a bit lager may, or may not, provide better results.
            while (count < 10000)
            {
                total += in_port.Read();
                count++;
                //ts = DateTime.Now - start;
            }
            calibration_value = total / count;
            BlinkLed();
            return;
        }
        private static void vonNeumann(int input)
        {
            if (input != previous)
            {
                byt = byt + input.ToString();
                previous = (in_port.Read() > calibration_value) ? 0 : 1;
            }
        }
        private static void ExclusiveOr(int input)
        {
            flip_flop = (flip_flop == 1) ? 0 : 1;
            byt = byt + (flip_flop ^ input).ToString();
        }
        private static void BlinkLed()
        {
            led.Write(true);
            Thread.Sleep(30);
            led.Write(false);
        }

        public static void Main()
        {
            Calibrate();
            //setup Von Neumann
            previous = (in_port.Read() > calibration_value) ? 1 : 0;
            Debug.Print("Loop");
            while(true)
                Loop();
        }
        private static void Output()
        {
            //Dont have an LCD to output to yet...
            Debug.Print(byt + " = " + ParseBinary(byt).ToString());
            byt = "";
        }
        public static long ParseBinary(string input)
        {
            //Thanks to Jon Skeet for this one http://stackoverflow.com/questions/4281649/convert-binary-to-int-without-convert-toint32/4282972#4282972

            // Count up instead of down - it doesn't matter which way you do it
            long output = 0;
            for (int i = 0; i < input.Length; i++)
            {
                if (input[i] == '1')
                {
                    output |= 1 << (input.Length - i - 1);
                }
            }
            return output;
        }
    }
}

 

The first thing we do is to calibrate the device, because as the device ages the output can drift a bit.  We read the values from the ADC 10,000 times and average the readings, which gives us our middle point, anytime we read a value higher than this, we will make it a 1, and when we read lower it is a 0.  We can use this to create either numbers or letters, since its simply a binary stream.  It is a good idea to have some filtering of the output and I have implimented 2 methods to do that vonNeumann and ExclusiveOr.  The vonNeumann provides the best results, however I find that in most cases I don't need to use it.  Your results will vary based on how noisy your enviornment is, I find that when I head out on the lake the numbers are far more stable then when I'm at home or even just in town.  I could imagine that around large motors (such as those in factories) you will find more noise in your output.

The PCB that resulted from this design is available for purchase,I may make up a quick kit and make that available.

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments (1)

hello im new to all of Netduino and was wondering if you have code for converting the random binary derived digits into hash that fills up a text file without the single binary or limited random digits like on the video? I want to make a text file filled with random numbers but no binary or = or spaces between the numbers hashing the double digits would produce a larger amount of digits but im unsure how random it would be, I plan on using Dieharder true random testing suite to test its randomness

April 3, 2012 | Unregistered CommenterJR

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>