Introduction: Arduino Truly Random Number Generator

Before we get started, its important to know the significance of Truly Random Numbers in out life, certainly the concept isn't new but it affects our life most nowadays.

Random numbers are the backbone of modern world, used every where from gambling to banking, cryptography which drives the whole internet. Its is utmost important that random numbers used are actually random in nature.

There are many ways of generating random numbers some are easy and fast while others bit harder and slow. Ideally we want something that can generate fast random numbers and easy to implement but considering security in mind its harder (mostly) and slow ways that are more secure.

This topic became very hot when window XP encountered random number generator bug in 2012 and Intel found having backdoor in Rd-Rand (physical chip responsible for generating random numbers on Intel chips).

The ways of generating random numbers gave rise to two type of numbers, first- the Pseudo Random Numbers (enough random to get the work done) and the second, Truly Random Numbers.

Supplies

  • Arduino

Step 1: "Pseudo" Random Numbers

Pseudo Random Number are generated by an algorithm (Linear Congruential Generator is most used and the oldest algorithm) that uses mathematical formulas to produce sequences of random numbers. Pseudo Random Number Generator generate a sequence of numbers approximating the properties of random numbers. A Pseudo Random Number Generator starts from a value called seed value which is taken from physical outside environment, like fan rpm, cpu temp or other things that are appear to be random. Main benefit being fast, many numbers are generated in a short time, but can also be reproduced later, if the starting point in the sequence is known. Hence, the numbers are deterministic, not truly random. The algorithm also start repeating itself after a certain period with make reproducing numbers more easier (still not that easy by any mean).

If interested, read more about Linear Congruential Generator here.

Step 2: "Truly" Random Numbers

The Truly Random Numbers are real random numbers and are generated using an entropy source, and from thermodynamics we know, entropy is very closely related with randomness and it always increases which guaranties true randomness. The major drawback is the slow speed generation of symbols compared to conventional Pseudo Random Numbers generators.

The classical mechanics is more or less deterministic, that's why Truly Random Number generators are based on quantum mechanics.

If you are reading all you might find these videos interesting:

https://www.youtube.com/watch?v=tClZGWlRLoE

https://www.youtube.com/watch?v=sufAlWP4Ak8

Step 3: Truly Random Number Generator With Arduino

To generate Truly Random Number, the value should be from a totally unpredictable source and in case of arduino we could use the mixture of up time (millies()) value, the analogRead() value on one floating analog pin of arduino or in case of any micro-controller with built in temp sensor, the difference of many consecutive temperature readings, but these all above mentioned methods are acceptable but not satisfying enough.

Here comes the god of all methods, The clock drift sampling method, where we sample one clock with another clock and because there is some drift b/w the two clocks, the difference appears totally random. Any arduino board can be used as all have two different clock, one from crystal resonator and there one from RC resonator used for watchdog timer.

#include <stdint.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>

byte output = 0;  //holds the binary output value
byte sample = 0;
byte current_bit = 0;
boolean waiting = false;  //bool true when ISR runs

void setup() {
Serial.begin(115200);
wd_setup();  //setting up the watchdog timer
}

void loop(){
if (waiting) {
  output = rotate(output, 1);      
  output ^= sample;           // XOR preserves randomness
  current_bit++;
  waiting = false;            //so that the loop() runs only once and after ISR

  if (current_bit > 7){
      Serial.println(output,BIN); // printing the raw binary value
      current_bit = 0;
    }
  }
}

byte rotate(const byte val, int shift) {    //rotate the bits to the left to increase the randomness

    if ((shift &= sizeof(val)*8 - 1) == 0)
          return val;
    return (val << shift) | (val >> (sizeof(val)*8 - shift));
}

void wd_setup() {   //sets the WD timer in interrupt mode with shortest prescaler
    cli();
    MCUSR = 0;
      
  WDTCSR |= _BV(WDCE) | _BV(WDE);
  WDTCSR = _BV(WDIE);
  sei();
}
  
// Watchdog Timer Interrupt Service Routine
ISR(WDT_vect){
  /* only sampling the clock of cpu
    which are only last 8 bits of the time
    so ignoring the higher bits*/
  
    sample = TCNT1L;
    waiting = true;
  }


Best part is, no external component is required. But as per the drawback,you will only get around 7 bytes per sec of random data.

If you want to know more, https://gist.github.com/endolith/2568571

Step 4: In the End

The classical physics is much more deterministic then we think. Everything we observe is less and less random. Perceived randomness is there only till we can't compute all the possible variables classical physical world has to offer.

This is why we are have quantum mechanics (more precisely, the noise at quantum level) for the help.